diff --git a/joint_teapot/app.py b/joint_teapot/app.py index f3fc6a4..3899381 100644 --- a/joint_teapot/app.py +++ b/joint_teapot/app.py @@ -3,6 +3,7 @@ from datetime import datetime from pathlib import Path from typing import List +from filelock import FileLock from git import Repo from typer import Argument, Option, Typer, echo @@ -249,34 +250,40 @@ def joj3_scoreboard( logger.info(f"debug log to file: {settings.log_file_path}") if joj3.check_skipped(score_file_path, "skip-scoreboard"): return - repo_path = tea.pot.git.repo_clean_and_checkout(repo_name, "grading") - repo: Repo = tea.pot.git.get_repo(repo_name) - if "grading" not in repo.remote().refs: - logger.error( - '"grading" branch not found in remote, create and push it to origin first.' + lock = FileLock( + settings.joj3_lock_file_path, timeout=settings.joj3_lock_file_timeout + ) + with lock.acquire(): + repo_path = tea.pot.git.repo_clean_and_checkout(repo_name, "grading") + repo: Repo = tea.pot.git.get_repo(repo_name) + if "grading" not in repo.remote().refs: + logger.error( + '"grading" branch not found in remote, create and push it to origin first.' + ) + return + if "grading" not in repo.branches: + logger.error('"grading" branch not found in local, create it first.') + return + repo.git.reset("--hard", "origin/grading") + joj3.generate_scoreboard( + score_file_path, + submitter, + os.path.join(repo_path, scoreboard_file_name), + exercise_name, + ) + actions_link = ( + f"https://{settings.gitea_domain_name}{settings.gitea_suffix}/" + + f"{settings.gitea_org_name}/{submitter_repo_name}/" + + f"actions/runs/{run_number}" + ) + commit_message = ( + f"joj3: update scoreboard by @{submitter} in " + + f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" + + f"gitea actions link: {actions_link}" + ) + tea.pot.git.add_commit_and_push( + repo_name, [scoreboard_file_name], commit_message ) - return - if "grading" not in repo.branches: - logger.error('"grading" branch not found in local, create it first.') - return - repo.git.reset("--hard", "origin/grading") - joj3.generate_scoreboard( - score_file_path, - submitter, - os.path.join(repo_path, scoreboard_file_name), - exercise_name, - ) - actions_link = ( - f"https://{settings.gitea_domain_name}{settings.gitea_suffix}/" - + f"{settings.gitea_org_name}/{submitter_repo_name}/" - + f"actions/runs/{run_number}" - ) - commit_message = ( - f"joj3: update scoreboard by @{submitter} in " - + f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" - + f"gitea actions link: {actions_link}" - ) - tea.pot.git.add_commit_and_push(repo_name, [scoreboard_file_name], commit_message) @app.command( @@ -318,43 +325,47 @@ def joj3_failed_table( logger.info(f"debug log to file: {settings.log_file_path}") if joj3.check_skipped(score_file_path, "skip-failed-table"): return - repo_path = tea.pot.git.repo_clean_and_checkout(repo_name, "grading") - repo: Repo = tea.pot.git.get_repo(repo_name) - if "grading" not in repo.remote().refs: - logger.error( - '"grading" branch not found in remote, create and push it to origin first.' + lock = FileLock( + settings.joj3_lock_file_path, timeout=settings.joj3_lock_file_timeout + ) + with lock.acquire(): + repo_path = tea.pot.git.repo_clean_and_checkout(repo_name, "grading") + repo: Repo = tea.pot.git.get_repo(repo_name) + if "grading" not in repo.remote().refs: + logger.error( + '"grading" branch not found in remote, create and push it to origin first.' + ) + return + if "grading" not in repo.branches: + logger.error('"grading" branch not found in local, create it first.') + return + repo.git.reset("--hard", "origin/grading") + submitter_repo_link = ( + f"https://{settings.gitea_domain_name}{settings.gitea_suffix}/" + + f"{settings.gitea_org_name}/{submitter_repo_name}" + ) + actions_link = ( + f"https://{settings.gitea_domain_name}{settings.gitea_suffix}/" + + f"{settings.gitea_org_name}/{submitter_repo_name}/" + + f"actions/runs/{run_number}" + ) + joj3.generate_failed_table( + score_file_path, + submitter_repo_name, + submitter_repo_link, + os.path.join(repo_path, failed_table_file_name), + actions_link, + ) + commit_message = ( + f"joj3: update failed table by @{submitter} in " + + f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" + + f"gitea actions link: {actions_link}" + ) + tea.pot.git.add_commit_and_push( + repo_name, + [failed_table_file_name], + commit_message, ) - return - if "grading" not in repo.branches: - logger.error('"grading" branch not found in local, create it first.') - return - repo.git.reset("--hard", "origin/grading") - submitter_repo_link = ( - f"https://{settings.gitea_domain_name}{settings.gitea_suffix}/" - + f"{settings.gitea_org_name}/{submitter_repo_name}" - ) - actions_link = ( - f"https://{settings.gitea_domain_name}{settings.gitea_suffix}/" - + f"{settings.gitea_org_name}/{submitter_repo_name}/" - + f"actions/runs/{run_number}" - ) - joj3.generate_failed_table( - score_file_path, - submitter_repo_name, - submitter_repo_link, - os.path.join(repo_path, failed_table_file_name), - actions_link, - ) - commit_message = ( - f"joj3: update failed table by @{submitter} in " - + f"{settings.gitea_org_name}/{submitter_repo_name}@{commit_hash}\n\n" - + f"gitea actions link: {actions_link}" - ) - tea.pot.git.add_commit_and_push( - repo_name, - [failed_table_file_name], - commit_message, - ) @app.command( diff --git a/joint_teapot/config.py b/joint_teapot/config.py index 027140e..2c0bbb1 100644 --- a/joint_teapot/config.py +++ b/joint_teapot/config.py @@ -35,9 +35,13 @@ class Settings(BaseSettings): "charlem", ] - # sid + # joj joj_sid: str = "" + # joj3 + joj3_lock_file_path: str = ".git/teapot.lock" + joj3_lock_file_timeout: int = 30 + # log file log_file_path: str = "joint-teapot.log" stderr_log_level: str = "INFO" diff --git a/requirements.txt b/requirements.txt index d58f716..53d58bc 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ canvasapi>=2.2.0 colorama>=0.4.6 +filelock>=3.14.0 focs_gitea>=1.22.0 GitPython>=3.1.18 joj-submitter>=0.0.8