feat: joj3 check

This commit is contained in:
张泊明518370910136 2024-11-25 04:32:30 -05:00
parent da28e15a28
commit dd9c150598
GPG Key ID: CA088E6D9284F870

View File

@ -1,5 +1,6 @@
import json
import os
import re
from datetime import datetime, timedelta
from pathlib import Path
from time import sleep
@ -13,6 +14,7 @@ from joint_teapot.config import Settings, set_settings, settings
from joint_teapot.teapot import Teapot
from joint_teapot.utils import joj3
from joint_teapot.utils.logger import logger, set_logger
from joint_teapot.utils.main import first
if TYPE_CHECKING:
import focs_gitea
@ -637,6 +639,88 @@ def joj3_all(
sleep(retry_interval)
@app.command(
"joj3-check",
help="check joj3 restrictions",
)
def joj3_check(
env_path: str = Argument("", help="path to .env file"),
submitter: str = Argument("", help="submitter ID"),
repo_name: str = Argument(
"",
help="name of grading repo to push scoreboard file",
),
submitter_repo_name: str = Argument(
"",
help="repository's name of the submitter",
),
scoreboard_file_name: str = Argument(
"scoreboard.csv", help="name of scoreboard file in the gitea repo"
),
exercise_name: str = Argument(
"unknown",
help="name of the exercise that appears on the issue title",
),
group_config: str = Option(
...,
help=(
"Configuration for groups in the format "
"'group_name=max_count:time_period(in hours)'. "
"Empty group name for all groups. "
"Negative max_count or time_period for no limit. "
"Example: --group-config joj=10:24,run=20:48"
),
),
) -> None:
set_settings(Settings(_env_file=env_path))
set_logger(settings.stderr_log_level, diagnose=False, backtrace=False)
repo: Repo = tea.pot.git.get_repo(repo_name)
now = datetime.now()
items = group_config.split(",")
for item in items:
group, values = item.split("=")
max_count, time_period = map(int, values.split(":"))
if max_count < 0 or time_period < 0:
continue
since = now - timedelta(hours=time_period)
since_git_format = since.strftime("%Y-%m-%dT%H:%M:%S")
submit_count = 0
commits = repo.iter_commits(paths=scoreboard_file_name, since=since_git_format)
for commit in commits:
msg = commit.message.strip()
lines = msg.splitlines()
pattern = (
r"joj3: update scoreboard for (?P<exercise_name>.+?) "
r"by @(?P<submitter>.+) in "
r"(?P<gitea_org_name>.+)/(?P<submitter_repo_name>.+)@(?P<commit_hash>.+)" # 捕获 gitea_org_name, submitter_repo_name 和 commit_hash
)
match = re.match(pattern, lines[0])
if not match:
continue
d = match.groupdict()
if (
exercise_name != d["exercise_name"]
or submitter != d["submitter"]
or submitter_repo_name != d["submitter_repo_name"]
):
continue
if group != "":
line = first(lines, lambda l: l.startswith("groups: "))
if line is not None:
groups = line[len("groups: ") :].split(",")
if group not in groups:
continue
submit_count += 1
if submit_count > max_count:
logger.error(
f"submitter {submitter} has submitted too many times, "
f"group={group}, "
f"time period={time_period} hour(s), "
f"max count={max_count}, submit count={submit_count}"
)
raise Exit(code=1)
if __name__ == "__main__":
try:
app()