dev #10

Merged
李衍志523370910113 merged 238 commits from dev into master 2025-03-05 16:20:39 +08:00
16 changed files with 2702 additions and 175 deletions
Showing only changes of commit c67dd32cf2 - Show all commits

View File

@ -5,10 +5,10 @@ from typing import Any, List
import rtoml
from joj3_config_generator.models import joj1, repo, result, task
from joj3_config_generator.processers.repo import (
from joj3_config_generator.processers.repo import ( # get_teapotcheck_config,
get_healthcheck_config,
get_teapot_config,
get_teapotcheck_config,
get_teapot_stage,
)
from joj3_config_generator.processers.task import (
fix_diff,
@ -34,13 +34,17 @@ def convert(repo_conf: repo.Config, task_conf: task.Config) -> result.Config:
),
# FIXME: don't hardcode
actor_csv_path="/home/tt/.config/joj/students.csv",
stage=result.Stage(stages=[], sandbox_token=repo_conf.sandbox_token),
stage=result.Stage(
jon-lee marked this conversation as resolved Outdated

where is it used?

where is it used?

this should be storing all the files that are about to be copy in or out

this should be storing all the files that are about to be copy in or out

It is as the input and output for the following functions about parsers

It is as the input and output for the following functions about parsers

so this feature is not implemented?

so this feature is not implemented?
    if not repo_conf.force_skip_health_check_on_test or not current_test:
        result_conf.stage.stages.append(get_health_check_config(repo_conf))
    cached: List[str] = []
    # Convert each stage in the task configuration
    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)
        conf_stage = get_conf_stage(task_stage, executor_with_config)
        conf_stage = fix_result_detail(task_stage, conf_stage)
        conf_stage = fix_dummy(task_stage, conf_stage)
        conf_stage = fix_keyword(task_stage, conf_stage)
        conf_stage = fix_file(task_stage, conf_stage)
        conf_stage = fix_diff(task_stage, conf_stage, task_conf)
        result_conf.stage.stages.append(conf_stage)

it is

    for task_stage in task_conf.stages:
        executor_with_config, cached = get_executor_with_config(task_stage, cached)

this is a loop, so this cached will be updated in every round of stage

```python if not repo_conf.force_skip_health_check_on_test or not current_test: result_conf.stage.stages.append(get_health_check_config(repo_conf)) cached: List[str] = [] # Convert each stage in the task configuration for task_stage in task_conf.stages: executor_with_config, cached = get_executor_with_config(task_stage, cached) conf_stage = get_conf_stage(task_stage, executor_with_config) conf_stage = fix_result_detail(task_stage, conf_stage) conf_stage = fix_dummy(task_stage, conf_stage) conf_stage = fix_keyword(task_stage, conf_stage) conf_stage = fix_file(task_stage, conf_stage) conf_stage = fix_diff(task_stage, conf_stage, task_conf) result_conf.stage.stages.append(conf_stage) ``` it is ```python for task_stage in task_conf.stages: executor_with_config, cached = get_executor_with_config(task_stage, cached) ``` this is a loop, so this `cached` will be updated in every round of stage

The return value is unnecessary.

The return value is unnecessary.

I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage.

I have a lazing coding style here, everything has get imported would get exported, so should maintain this until the end of the loop. Everything is exported in previous stage would be imported in the next stage.
  1. The return value is unnecessary
  2. It should be a set
1. The return value is unnecessary 2. It should be a `set`

try it yourself

try it yourself

I see why

I see why

resolved.

resolved.
stages=[],
sandbox_token=repo_conf.sandbox_token,
poststages=[get_teapot_stage(repo_conf)],
),
teapot=get_teapot_config(repo_conf, task_conf),
)
# Construct healthcheck stage
healthcheck_stage = get_healthcheck_config(repo_conf)
teapotcheck_stage = get_teapotcheck_config(repo_conf, task_conf)
# teapotcheck_stage = get_teapotcheck_config(repo_conf, task_conf)
result_conf.stage.stages.append(healthcheck_stage)
jon-lee marked this conversation as resolved Outdated

forgot to uncommented 😭

forgot to uncommented 😭

fixed

fixed
cached: List[str] = []
# Convert each stage in the task configuration
@ -65,7 +69,7 @@ def convert_joj1(joj1_conf: joj1.Config) -> task.Config:
# You can define a command based on language properties
command = f"run {language.language}"
# Assuming we don't have explicit files, we will set empty ones or default behavior
files = task.Files(import_=[], export=[])
files = task.Files(import_=[], export=[]) # type: ignore
# Score can be derived from the first case or set to a default
score = 0
parsers: List[str] = [] # Define parsers if applicable
@ -121,4 +125,3 @@ def distribute_json(folder_path: str, repo_obj: Any) -> None:
assert os.path.exists(
json_file_path
), f"Failed to convert {toml_file_path} into json!"
return 0

View File

@ -15,9 +15,7 @@ class Group(BaseModel):
class Config(BaseModel):
teaching_team: List[str]
max_size: float = Field(..., ge=0)
release_tags: List[str]
files: Files
sandbox_token: str
max_total_score: int = Field(100)

View File

@ -16,8 +16,8 @@ class CmdFile(BaseModel):
class Cmd(BaseModel):
args: list[str]
env: list[str] = ["PATH=/usr/bin:/bin:/usr/local/bin"]
args: Optional[List[str]] = None
env: Optional[List[str]] = ["PATH=/usr/bin:/bin:/usr/local/bin"]
stdin: Optional[CmdFile] = CmdFile(content="")
stdout: Optional[CmdFile] = CmdFile(name="stdout", max=4 * 1024)
stderr: Optional[CmdFile] = CmdFile(name="stderr", max=4 * 1024)
@ -27,12 +27,12 @@ class Cmd(BaseModel):
memory_limit: int = Field(800 * 1024 * 1024, serialization_alias="memoryLimit")
stack_limit: int = Field(0, serialization_alias="stackLimit")
proc_limit: int = Field(50, serialization_alias="procLimit")
proc_limit: int = Field(50, serialization_alias="procLimit")
cpu_rate_limit: int = Field(0, serialization_alias="cpuRateLimit")
jon-lee marked this conversation as resolved Outdated

unit?

unit?

I think timeparse and humanfriendly would deal wth that?

I think `timeparse` and `humanfriendly` would deal wth that?

resolved.

resolved.
cpu_set_limit: str = Field("", serialization_alias="cpuSetLimit")
copy_in: Dict[str, CmdFile] = Field({}, serialization_alias="copyIn")
copy_in_cached: Dict[str, str] = Field({}, serialization_alias="copyInCached")
copy_in_dir: str = Field(".", serialization_alias="copyInDir")
# reconsider this default situation
copy_out: List[str] = Field(["stdout", "stderr"], serialization_alias="copyOut")
copy_out_cached: List[str] = Field([], serialization_alias="copyOutCached")
copy_out_max: int = Field(0, serialization_alias="copyOutMax")
@ -46,7 +46,6 @@ class Cmd(BaseModel):
class OptionalCmd(BaseModel):
args: Optional[list[str]] = None
env: Optional[list[str]] = ["PATH=/usr/bin:/bin:/usr/local/bin"]
env: Optional[list[str]] = ["PATH=/usr/bin:/bin:/usr/local/bin"]
stdin: Optional[CmdFile] = None
stdout: Optional[CmdFile] = None
stderr: Optional[CmdFile] = None
@ -60,7 +59,6 @@ class OptionalCmd(BaseModel):
)
stack_limit: Optional[int] = Field(None, serialization_alias="stackLimit")
proc_limit: Optional[int] = Field(50, serialization_alias="procLimit")
jon-lee marked this conversation as resolved Outdated

What is the conclusion?

What is the conclusion?

should be already solved.

should be already solved.
proc_limit: Optional[int] = Field(50, serialization_alias="procLimit")
cpu_rate_limit: Optional[int] = Field(None, serialization_alias="cpuRateLimit")
cpu_set_limit: Optional[str] = Field(None, serialization_alias="cpuSetLimit")
copy_in: Optional[Dict[str, CmdFile]] = Field(None, serialization_alias="copyIn")
@ -88,14 +86,7 @@ class OptionalCmd(BaseModel):
)
class Stage(BaseModel):
name: str
group: Optional[str] = None
executor: "ExecutorConfig"
parsers: list["ParserConfig"]
class ExecutorWithConfig(BaseModel):
class ExecutorWith(BaseModel):
default: Cmd
cases: List[OptionalCmd]
@ -105,7 +96,7 @@ class Executor(BaseModel):
with_: ExecutorWith = Field(..., serialization_alias="with")
class Parser(BaseModel):
class ParserConfig(BaseModel):
name: str
with_: Dict[str, Any] = Field(..., serialization_alias="with")
@ -114,7 +105,7 @@ class StageDetail(BaseModel):
name: str
group: Optional[str] = ""
executor: Executor
parsers: List[Parser]
parsers: List[ParserConfig]
class Stage(BaseModel):
@ -126,6 +117,8 @@ class Stage(BaseModel):
"/tmp/joj3_result.json", serialization_alias="outputPath"
) # nosec: B108
stages: List[StageDetail]
prestages: Optional[List[StageDetail]] = None
poststages: List[StageDetail]
class Teapot(BaseModel):
jon-lee marked this conversation as resolved Outdated

Should it be optional?

Should it be optional?
@ -147,9 +140,10 @@ class Teapot(BaseModel):
class Config(BaseModel):
name: str = "unknown"
name: str = ""
log_path: str = Field("", serialization_alias="logPath")
expire_unix_timestamp: int = Field(-1, serialization_alias="expireUnixTimestamp")
actor_csv_path: str = Field("", serialization_alias="actorCsvPath")
actor_csv_path: str = Field("", serialization_alias="actorpostStagesCsvPath")
max_total_score: int = Field(100, serialization_alias="maxTotalScore")
stage: Stage
teapot: Teapot
teapot: Teapot # FIXME: remove this

View File

@ -1,5 +1,5 @@
from datetime import datetime
jon-lee marked this conversation as resolved Outdated

every field in this file should not be optional. we give an default value here if any field does not exist

every field in this file should not be optional. we give an default value here if any field does not exist

and use underscore naming in this file

and use underscore naming in this file

every field in this file should not be optional. we give an default value here if any field does not exist

fixed

> every field in this file should not be optional. we give an default value here if any field does not exist fixed

and use underscore naming in this file

fixed.

> and use underscore naming in this file fixed.
from typing import Any, Dict, Optional, Type
from typing import Any, Dict, List, Optional, Type
from pydantic import BaseModel, Field, root_validator
@ -13,7 +13,13 @@ class ParserResultDetail(BaseModel):
class ParserFile(BaseModel):
name: str = None
name: Optional[str] = None
class ParserLog(BaseModel):
fileName: Optional[str] = None
msg: Optional[str] = None
level: Optional[str] = None
class ParserDummy(BaseModel):
@ -54,6 +60,7 @@ class Stage(BaseModel):
name: Optional[str] = None # Stage name
group: Optional[str] = None # TODO: may need to formulate this
path: Optional[str] = None # FIXME: this is highly possible to be removed in future
env: Optional[list[str]] = None
command: Optional[str] = None # Command to run
files: Optional[Files] = None
in_: Optional[str] = Field(None, alias="in")
@ -72,8 +79,9 @@ class Stage(BaseModel):
)
file: Optional[ParserFile] = ParserFile()
skip: Optional[list[str]] = []
diff: Optional[ParserDiff] = ParserDiff()
# cases related
cases: Optional[Dict[str, "Stage"]] = {}
diff: Optional[ParserDiff] = ParserDiff()
jon-lee marked this conversation as resolved Outdated

deprecated

deprecated

@bomingzh any suggestions on the structure?

@bomingzh any suggestions on the structure?
PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.9/migration/
``` PydanticDeprecatedSince20: Support for class-based `config` is deprecated, use ConfigDict instead. Deprecated in Pydantic V2.0 to be removed in V3.0. See Pydantic V2 Migration Guide at https://errors.pydantic.dev/2.9/migration/ ```

fixed with model_config

fixed with `model_config`

str here need to be a StrEnum now.

str here need to be a `StrEnum` now.

But I guess we don't know the set of case in advance, making it dynamic StrEnum is meaningless

But I guess we don't know the set of case in advance, making it dynamic `StrEnum` is meaningless

line changed, the comment is for parsers

line changed, the comment is for `parsers`
class Config:
extra = "allow"
jon-lee marked this conversation as resolved Outdated

this should be the StrEnum

this should be the `StrEnum`

It is supported now.

It is supported now.

View File

@ -1,5 +1,6 @@
import hashlib
import shlex
import socket
from pathlib import Path
from joj3_config_generator.models import repo, result, task
@ -7,8 +8,8 @@ from joj3_config_generator.models import repo, result, task
def get_grading_repo_name() -> str:
# FIXME: uncomment back when everything is ready!
jon-lee marked this conversation as resolved Outdated

make it a field in repo.toml, if it is unset, then use socket.gethostname. We set this value to pass the test.

make it a field in repo.toml, if it is unset, then use `socket.gethostname`. We set this value to pass the test.

resolved.

resolved.
host_name = "engr151"
# host_name = socket.gethostname()
# host_name = "engr151"
host_name = socket.gethostname()
return f"{host_name.split('-')[0]}-joj"
@ -50,7 +51,33 @@ def get_teapot_config(repo_conf: repo.Config, task_conf: task.Config) -> result.
return teapot
def get_healthcheck_cmd(repo_conf: repo.Config) -> result.Cmd:
def get_teapot_stage(repo_conf: repo.Config) -> result.StageDetail:
jon-lee marked this conversation as resolved Outdated

why not args = "hc -root=. "

why not `args = "hc -root=. "`

resolved.

resolved.
args_ = ""
args_ = (
args_
+ f"/usr/local/bin/joint-teapot joj3-all-env /home/tt/.config/teapot/teapot.env --grading-repo-name {get_grading_repo_name()} --max-total-score {repo_conf.max_total_score}"
jon-lee marked this conversation as resolved Outdated

do we need that default?

do we need that default?

what is the situation internally in JOJ3? I just added that blindly when I reached that stage. Overall I think 100 times per day should be a reasonable and safe default? considering that there may be group works and due date

what is the situation internally in JOJ3? I just added that blindly when I reached that stage. Overall I think 100 times per day should be a reasonable and safe default? considering that there may be group works and due date

They can manually add it if needed. Or just move it to the model default.

They can manually add it if needed. Or just move it to the model default.

removed.

removed.
)
stage_conf = result.StageDetail(
name="teapot",
executor=result.Executor(
name="local",
with_=result.ExecutorWith(
default=result.Cmd(
args=shlex.split(args_),
env=[
"LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"
], # TODO: fix it according to the task name
),
cases=[],
),
),
parsers=[result.ParserConfig(name="log", with_={"msg": "joj3 summary"})],
)
return stage_conf
def get_healthcheck_args(repo_conf: repo.Config) -> str:
repoSize = repo_conf.max_size
immutable = repo_conf.files.immutable
repo_size = f"-repoSize={str(repoSize)} "
@ -59,13 +86,13 @@ def get_healthcheck_cmd(repo_conf: repo.Config) -> result.Cmd:
for i, meta in enumerate(required_files):
required_files[i] = f"-meta={meta} "
immutable_files = f"-checkFileNameList="
immutable_files = "-checkFileNameList="
for i, name in enumerate(immutable):
if i == len(immutable) - 1:
immutable_files = immutable_files + name + " "
else:
immutable_files = immutable_files + name + ","
chore = f"/tmp/repo-health-checker -root=. "
chore = "/usr/local/bin/repo-health-checker -root=. "
args = ""
args = args + chore
args = args + repo_size
@ -76,26 +103,25 @@ def get_healthcheck_cmd(repo_conf: repo.Config) -> result.Cmd:
args = args + immutable_files
cmd = result.Cmd(
args=shlex.split(args),
copy_in={
# This path is hardcoded
f"/tmp/repo-health-checker": result.CmdFile(
src="/usr/local/bin/repo-health-checker"
)
},
return args
def get_debug_args(repo_conf: repo.Config) -> str:
args = ""
args = (
args
+ f"/usr/local/bin/joint-teapot joj3-check-env /home/tt/.config/teapot/teapot.env --grading-repo-name {get_grading_repo_name()} --group-config"
)
return cmd
def get_teapotcheck_cmd(repo_conf: repo.Config, task_conf: task.Config) -> result.Cmd:
return 0
def get_teapotcheck_config(
repo_conf: repo.Config, task_conf: task.Config
) -> result.StageDetail:
return 0
group_config = ""
for i, name in enumerate(repo_conf.groups.name):
group_config = (
group_config
+ f"{name}={repo_conf.groups.max_count[i]}:{repo_conf.groups.time_period_hour[i]},"
)
# default value hardcoded
group_config = group_config + "=100:24"
args = args + group_config
return args
def get_healthcheck_config(repo_conf: repo.Config) -> result.StageDetail:
@ -103,10 +129,24 @@ def get_healthcheck_config(repo_conf: repo.Config) -> result.StageDetail:
name="healthcheck",
group="",
executor=result.Executor(
name="sandbox",
with_=result.ExecutorWith(default=get_healthcheck_cmd(repo_conf), cases=[]),
name="local",
with_=result.ExecutorWith(
default=result.Cmd(),
cases=[
result.OptionalCmd(
args=shlex.split(get_healthcheck_args(repo_conf)),
),
result.OptionalCmd(
args=shlex.split(get_debug_args(repo_conf)),
env=["LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"],
),
],
),
),
parsers=[ParserConfig(name="healthcheck", with_={"score": 0, "comment": ""})],
parsers=[
result.ParserConfig(name="healthcheck", with_={"score": 1}),
result.ParserConfig(name="debug", with_={"score": 1}),
],
)
return healthcheck_stage
@ -124,9 +164,6 @@ def get_hash(immutable_files: list[str]) -> str: # input should be a list
current_file_path = Path(__file__).resolve()
project_root = current_file_path.parents[2]
file_path = f"{project_root}/tests/immutable_p3-test/"
# file_path = f"{project_root}/tests/immutable_hteam/"
# file_path = f"{project_root}/tests/immutable_hteam-test/"
# file_path = f"{project_root}/tests/immutable_p3/"
immutable_hash = []
for i, file in enumerate(immutable_files):
immutable_files[i] = file_path + file.rsplit("/", 1)[-1]

View File

@ -21,7 +21,10 @@ def get_conf_stage(
with_=executor_with_config,
),
parsers=(
[result.Parser(name=parser, with_={}) for parser in task_stage.parsers]
[
result.ParserConfig(name=parser, with_={})
for parser in task_stage.parsers
]
if task_stage.parsers is not None
else []
),
@ -69,7 +72,12 @@ def get_executorWithConfig(
for file in copy_in_files
},
stdin=(
result.CmdFile(content="") if "diff" not in task_stage.parsers else None
result.CmdFile(content="")
if (
jon-lee marked this conversation as resolved Outdated

do not use getattr, visit the field explictly

do not use `getattr`, visit the field explictly

resolved.

resolved.
(task_stage.parsers is not None)
and ("diff" not in task_stage.parsers)
)
jon-lee marked this conversation as resolved Outdated

is there a conclusion now? or it should have a prefix TODO: ?

is there a conclusion now? or it should have a prefix `TODO: `?

so far works fine on 280 sides, indicating that pbs in 151 can be resolved with proper guidelines I think.

so far works fine on 280 sides, indicating that pbs in 151 can be resolved with proper guidelines I think.

ok, then add that prefix

ok, then add that prefix
else None
jon-lee marked this conversation as resolved Outdated

is it in the correct unit?
Give all the fields in Limit a default value and make it non optional in task_stage.limit

is it in the correct unit? Give all the fields in `Limit` a default value and make it non optional in task_stage.limit

resolved

resolved
),
copy_out=copy_out_files,
copy_in_cached={file: file for file in cached},
@ -274,9 +282,7 @@ def fix_diff(
src=f"/home/tt/.config/joj/{task_conf.task.type_}/{stdin}"
# src=f"/home/tt/.config/joj/{task_stage.path}/{stdin}"
),
args=(
shlex.split(case_stage.command) if command is not None else None
),
args=(shlex.split(command) if command is not None else None),
cpu_limit=cpu_limit,
clock_limit=clock_limit,
memory_limit=memory_limit,

View File

@ -1,23 +1,15 @@
teaching_team = ["prof_john", "ta_alice", "ta_bob"]
max_size = 50.5
release_tags = ["v1.0", "v2.0", "final"]
sandbox_token = "test"
# reconfigure later
max_total_score = 100
# for projects
#groups.name = ["build", "run"]
#groups.max_count = [8, 5]
#groups.time_period_hour = [24, 24]
max_size = 50.5
# for tests
groups.name = ["joj", "run"]
groups.max_count = [1000, 1000]
groups.time_period_hour = [24, 24]
[groups]
name = ["joj", "run"]
max_count = [1000, 1000]
time_period_hour = [24, 24]
[files]
# projects
# required = ["README.md", "Changelog.md"]
required = ["README.md"]
immutable = [".gitignore", ".gitattributes",".gitea/workflows/push.yaml", ".gitea/workflows/release.yaml" ]
required = ["README.md", "Changelog.md"]
immutable = [".gitignore", ".gitattributes",".gitea/workflows/push.yaml", ".gitea/workflows/release.yaml"]

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +1,460 @@
# general task configuration
task.name = "e2" # task name
task.type = "exam/e2"
task.name = "hw7 ex2" # task name
task.type = "homework/h7/e2"
release.deadline = 2024-12-30 23:59:59+08:00
release.stages = [ "compile" ]
[[stages]]
name = "[cq] Compilation"
command = "./tools/compile" # eg. script running cmake commands
files.import = [ "tools/compile", "h6/build/ex3-main.c", "h6/build/ex4-main.c", "h6/build/ex5-main.c", "h6/build/ex7-main.c" ]
files.export = [ "h6/build/ex2", "h6/build/ex2-asan", "h6/build/ex2-ubsan", "h6/build/ex2-msan", "h6/build/ex3", "h6/build/ex3-asan", "h6/build/ex3-ubsan", "h6/build/ex3-msan", "h6/build/ex4", "h6/build/ex4-asan", "h6/build/ex4-ubsan", "h6/build/ex4-msan", "h6/build/ex5", "h6/build/ex5-asan", "h6/build/ex5-ubsan", "h6/build/ex5-msan", "h6/build/ex6", "h6/build/ex6-asan", "h6/build/ex6-ubsan", "h6/build/ex6-msan", "h6/build/ex7", "h6/build/ex7-asan", "h6/build/ex7-ubsan", "h6/build/ex7-msan", "h6/build/ex3-main.c", "h6/build/ex4-main.c", "h6/build/ex5-main.c", "h6/build/ex7-main.c", "h6/build/compile_commands.json" ]
name = "healthcheck"
score = 1
# compile parsers ex
parsers = [ "result-detail", "result-status", "file" ]
# healthcheck parsers
parsers = ["healthcheck", "debug"]
cases0.command = "/usr/local/bin/repo-health-checker -repoSize=100"
case1.command = """/usr/local/bin/joint-teapot
joj3-check-env
/home/tt/.config/teapot/teapot.env"
--grading-repo-name
JOJ3-actions-examples
--group-config
joj=50:24,=100:24"""
case1.env = ["LOG_FILE_PATH=/home/tt/.cache/joint-teapot-debug.log"]
[[stages]]
name = "Compilation"
command = "./tools/compile" # eg. script running cmake commands
files.import = [ "tools/compile" ]
files.export = [ "h7/build/ex2", "h7/build/ex2-asan", "h7/build/ex2-ubsan", "h7/build/ex2-msan", "h7/build/compile_commands.json" ]
score = 1
# compile parsers
parsers = [ "result-detail", "result-status" ]
result-status.comment = "Congratulations! Your code compiled successfully."
result-detail.exitstatus = true
result-detail.stderr = true
result-detail.time = false
result-detail.mem = false
result-status.forcequit = true
file.name = "stdout"
[[stages]]
name = "[cq] Filelength"
command = "./tools/filelength 400 300 *.cpp *.h"
files.import = [ "tools/filelength" ]
parsers = [ "keyword", "result-detail" ]
keyword.keyword = [ "max", "recommended"]
keyword.weight = [ 20, 10 ]
result-detail.exitstatus = true
result-detail.stdout = true
result-detail.time = false
result-detail.mem = false
[[stages]]
name = "[cq] Clang-tidy"
command = "run-clang-tidy-18 -header-filter=.* -quiet -load=/usr/local/lib/libcodequality.so -p h7/build h7/ex2.cpp"
files.import = [ "tests/homework/h7/.clang-tidy", "h7/build/compile_commands.json" ]
limit.stdout = 65
parsers = [ "clangtidy", "result-detail" ]
clangtidy.keyword = [ "codequality-unchecked-malloc-result", "codequality-no-global-variables", "codequality-no-header-guard", "codequality-no-fflush-stdin", "readability-function-size", "readability-duplicate-include", "readability-identifier-naming", "readability-redundant", "readability-misleading-indentation", "readability-misplaced-array-index", "cppcoreguidelines-init-variables", "bugprone-suspicious-string-compare", "google-global-names-in-headers", "clang-diagnostic", "clang-analyzer", "misc", "performance", "portability" ]
clangtidy.weight = [ 5, 20, 20, 20, 10, 5, 5, 5, 15, 5, 5, 5, 5, 5, 5, 5, 5, 5]
result-detail.exitstatus = true
result-detail.stdout = true
result-detail.time = false
result-detail.mem = false
[[stages]]
jon-lee marked this conversation as resolved Outdated

is it used?

is it used?

testcases in basic is intend to show a comprehensive situation.

testcases in basic is intend to show a comprehensive situation.

if unused, leave a comment

if unused, leave a comment

Then why is there a stdout field in class Limit

Then why is there a `stdout` field in `class Limit`

@bomingzh in toml now should we accept both 32m and 32 or just 32m now?

@bomingzh in toml now should we accept both `32m` and `32` or just `32m` now?

I reckon only 32m would be good

I reckon only `32m` would be good

yes, just str

yes, just str
name = "[cq] Cppcheck"
command = "cppcheck --template='{\"file\":\"{file}\",\"line\":{line}, \"column\":{column}, \"severity\":\"{severity}\", \"message\":\"{message}\", \"id\":\"{id}\"}' --force --enable=all --suppress=missingIncludeSystem --quiet h7/ex2.cpp"
limit.stderr = 65
parsers = [ "cppcheck", "result-detail" ]
cppcheck.keyword = ["error", "warning", "portability", "performance", "style"]
cppcheck.weight = [15, 5, 5, 5, 5]
result-detail.exitstatus = true
result-detail.stderr = true
result-detail.time = false
result-detail.mem = false
[[stages]]
name = "[cq] Cpplint"
command = "cpplint --linelength=120 --filter=-legal,-readability/casting,-whitespace,-runtime/printf,-runtime/threadsafe_fn,-runtime/int,-readability/todo,-build/include_subdir,-build/header_guard,-build/include_what_you_use --recursive --exclude=build h7/ex2.cpp"
limit.stdout = 65
parsers = [ "cpplint", "result-detail" ]
cpplint.keyword = [ "runtime", "readability", "build" ]
cpplint.weight = [ 5, 20, 10]
result-detail.exitstatus = true
result-detail.stderr = true
result-detail.time = false
result-detail.mem = false
[[stages]]
name = "[joj] ex2-asan"
group = "run"
command="./h7/build/ex2-asan -a"
files.import = [ "h7/build/ex2-asan" ]
limit.mem = 91224961
parsers = [ "diff", "result-detail" ]
result-detail.exitstatus = true
result-detail.stderr = true
# will be removed as long as the name is fixed
case0.diff.output.score = 5
case0.limit.cpu = 1
case0.limit.mem = 91224961
case0.diff.output.ignorespaces = true
#case0.limit.stdout = 8
#case0.command = "./h7/build/ex2"
case0.in = "case0.in"
case1.diff.output.score = 5
case1.limit.cpu = 1
case1.limit.mem = 91224961
case1.diff.output.ignorespaces = true
#case1.limit.stdout = 8
#case1.command = "./h7/build/ex2"
case1.in = "case1.in"
case2.diff.output.score = 5
case2.limit.cpu = 1
case2.limit.mem = 91224961
case2.diff.output.ignorespaces = true
#case2.limit.stdout = 8
#case2.command = "./h7/build/ex2"
case2.in = "case2.in"
case3.diff.output.score = 5
case3.limit.cpu = 1
case3.limit.mem = 91224961
case3.diff.output.ignorespaces = true
#case3.limit.stdout = 8
#case3.command = "./h7/build/ex2"
case3.in = "case3.in"
case4.diff.output.score = 10
case4.limit.cpu = 1
case4.limit.mem = 91224961
case4.diff.output.ignorespaces = true
#case4.limit.stdout = 8
#case4.command = "./h7/build/ex2"
case4.in = "case4.in"
case5.diff.output.score = 10
case5.limit.cpu = 1
case5.limit.mem = 91224961
case5.diff.output.ignorespaces = true
#case5.limit.stdout = 8
#case5.command = "./h7/build/ex2"
case5.in = "case5.in"
case6.diff.output.score = 15
case6.limit.cpu = 1
case6.limit.mem = 91224961
case6.diff.output.ignorespaces = true
#case6.limit.stdout = 8
#case6.command = "./h7/build/ex2"
case6.in = "case6.in"
case7.diff.output.score = 15
case7.limit.cpu = 1
case7.limit.mem = 91224961
case7.diff.output.ignorespaces = true
#case7.limit.stdout = 8
#case7.command = "./h7/build/ex2"
case7.in = "case7.in"
case8.diff.output.score = 15
case8.limit.cpu = 1
case8.limit.mem = 91224961
case8.diff.output.ignorespaces = true
#case8.limit.stdout = 8
#case8.command = "./h7/build/ex2"
case8.in = "case8.in"
case9.diff.output.score = 15
case9.limit.cpu = 1
case9.limit.mem = 91224961
case9.diff.output.ignorespaces = true
#case9.limit.stdout = 8
#case9.command = "./h7/build/ex2"
case9.in = "case9.in"
[[stages]]
name = "[joj] ex2-msan"
group = "joj"
command="./h7/build/ex2-msan -a"
files.import = [ "h7/build/ex2-msan" ]
limit.mem = 91224961
parsers = [ "diff", "result-detail" ]
result-detail.exitstatus = true
result-detail.stderr = true
# will be removed as long as the name is fixed
case0.diff.output.score = 5
case0.limit.cpu = 1
case0.limit.mem = 91224961
case0.diff.output.ignorespaces = true
#case0.limit.stdout = 8
#case0.command = "./h7/build/ex2"
case0.in = "case0.in"
case1.diff.output.score = 5
case1.limit.cpu = 1
case1.limit.mem = 91224961
case1.diff.output.ignorespaces = true
#case1.limit.stdout = 8
#case1.command = "./h7/build/ex2"
case1.in = "case1.in"
case2.diff.output.score = 5
case2.limit.cpu = 1
case2.limit.mem = 91224961
case2.diff.output.ignorespaces = true
#case2.limit.stdout = 8
#case2.command = "./h7/build/ex2"
case2.in = "case2.in"
case3.diff.output.score = 5
case3.limit.cpu = 1
case3.limit.mem = 91224961
case3.diff.output.ignorespaces = true
#case3.limit.stdout = 8
#case3.command = "./h7/build/ex2"
case3.in = "case3.in"
case4.diff.output.score = 10
case4.limit.cpu = 1
case4.limit.mem = 91224961
case4.diff.output.ignorespaces = true
#case4.limit.stdout = 8
#case4.command = "./h7/build/ex2"
case4.in = "case4.in"
case5.diff.output.score = 10
case5.limit.cpu = 1
case5.limit.mem = 91224961
case5.diff.output.ignorespaces = true
#case5.limit.stdout = 8
#case5.command = "./h7/build/ex2"
case5.in = "case5.in"
case6.diff.output.score = 15
case6.limit.cpu = 1
case6.limit.mem = 91224961
case6.diff.output.ignorespaces = true
#case6.limit.stdout = 8
#case6.command = "./h7/build/ex2"
case6.in = "case6.in"
case7.diff.output.score = 15
case7.limit.cpu = 1
case7.limit.mem = 91224961
case7.diff.output.ignorespaces = true
#case7.limit.stdout = 8
#case7.command = "./h7/build/ex2"
case7.in = "case7.in"
case8.diff.output.score = 15
case8.limit.cpu = 1
case8.limit.mem = 91224961
case8.diff.output.ignorespaces = true
#case8.limit.stdout = 8
#case8.command = "./h7/build/ex2"
case8.in = "case8.in"
case9.diff.output.score = 15
case9.limit.cpu = 1
case9.limit.mem = 91224961
case9.diff.output.ignorespaces = true
#case9.limit.stdout = 8
#case9.command = "./h7/build/ex2"
case9.in = "case9.in"
[[stages]]
name = "[joj] ex2-ubsan"
command="./h7/build/ex2-ubsan -a"
files.import = [ "h7/build/ex2-ubsan" ]
parsers = [ "diff", "result-detail" ]
result-detail.exitstatus = true
result-detail.stderr = true
# will be removed as long as the name is fixed
case0.diff.output.score = 5
case0.limit.cpu = 1
case0.limit.mem = 91224961
case0.diff.output.ignorespaces = true
#case0.limit.stdout = 8
#case0.command = "./h7/build/ex2"
case0.in = "case0.in"
case1.diff.output.score = 5
case1.limit.cpu = 1
case1.limit.mem = 91224961
case1.diff.output.ignorespaces = true
#case1.limit.stdout = 8
#case1.command = "./h7/build/ex2"
case1.in = "case1.in"
case2.diff.output.score = 5
case2.limit.cpu = 1
case2.limit.mem = 91224961
case2.diff.output.ignorespaces = true
#case2.limit.stdout = 8
#case2.command = "./h7/build/ex2"
case2.in = "case2.in"
case3.diff.output.score = 5
case3.limit.cpu = 1
case3.limit.mem = 91224961
case3.diff.output.ignorespaces = true
#case3.limit.stdout = 8
#case3.command = "./h7/build/ex2"
case3.in = "case3.in"
case4.diff.output.score = 10
case4.limit.cpu = 1
case4.limit.mem = 91224961
case4.diff.output.ignorespaces = true
#case4.limit.stdout = 8
#case4.command = "./h7/build/ex2"
case4.in = "case4.in"
case5.diff.output.score = 10
case5.limit.cpu = 1
case5.limit.mem = 91224961
case5.diff.output.ignorespaces = true
#case5.limit.stdout = 8
#case5.command = "./h7/build/ex2"
case5.in = "case5.in"
case6.diff.output.score = 15
case6.limit.cpu = 1
case6.limit.mem = 91224961
case6.diff.output.ignorespaces = true
#case6.limit.stdout = 8
#case6.command = "./h7/build/ex2"
case6.in = "case6.in"
case7.diff.output.score = 15
case7.limit.cpu = 1
case7.limit.mem = 91224961
case7.diff.output.ignorespaces = true
#case7.limit.stdout = 8
#case7.command = "./h7/build/ex2"
case7.in = "case7.in"
case8.diff.output.score = 15
case8.limit.cpu = 1
case8.limit.mem = 91224961
case8.diff.output.ignorespaces = true
#case8.limit.stdout = 8
#case8.command = "./h7/build/ex2"
case8.in = "case8.in"
case9.diff.output.score = 15
case9.limit.cpu = 1
case9.limit.mem = 91224961
case9.diff.output.ignorespaces = true
#case9.limit.stdout = 8
#case9.command = "./h7/build/ex2"
case9.in = "case9.in"
[[stages]]
name = "[joj] ex2"
group = "joj"
command="./h7/build/ex2"
files.import = [ "h7/build/ex2" ]
score = 10
parsers = [ "diff", "result-detail" ]
result-detail.exitstatus = true
result-detail.stderr = true
result-status.forcequit = true
# will be removed as long as the name is fixed
case0.diff.output.score = 5
case0.limit.cpu = 1
case0.limit.mem = 91224961
case0.diff.output.ignorespaces = true
#case0.limit.stdout = 8
#case0.command = "./h7/build/ex2"
case0.in = "case0.in"
case1.diff.output.score = 5
case1.limit.cpu = 1
case1.limit.mem = 91224961
case1.diff.output.ignorespaces = true
#case1.limit.stdout = 8
#case1.command = "./h7/build/ex2"
case1.in = "case1.in"
case2.diff.output.score = 5
case2.limit.cpu = 1
case2.limit.mem = 91224961
case2.diff.output.ignorespaces = true
#case2.limit.stdout = 8
#case2.command = "./h7/build/ex2"
case2.in = "case2.in"
case3.diff.output.score = 5
case3.limit.cpu = 1
case3.limit.mem = 91224961
case3.diff.output.ignorespaces = true
#case3.limit.stdout = 8
#case3.command = "./h7/build/ex2"
case3.in = "case3.in"
case4.diff.output.score = 10
case4.limit.cpu = 1
case4.limit.mem = 91224961
case4.diff.output.ignorespaces = true
#case4.limit.stdout = 8
#case4.command = "./h7/build/ex2"
case4.in = "case4.in"
case5.diff.output.score = 10
case5.limit.cpu = 1
case5.limit.mem = 91224961
case5.diff.output.ignorespaces = true
#case5.limit.stdout = 8
#case5.command = "./h7/build/ex2"
case5.in = "case5.in"
case6.diff.output.score = 15
case6.limit.cpu = 1
case6.limit.mem = 91224961
case6.diff.output.ignorespaces = true
#case6.limit.stdout = 8
#case6.command = "./h7/build/ex2"
case6.in = "case6.in"
case7.diff.output.score = 15
case7.limit.cpu = 1
case7.limit.mem = 91224961
case7.diff.output.ignorespaces = true
#case7.limit.stdout = 8
#case7.command = "./h7/build/ex2"
case7.in = "case7.in"
case8.diff.output.score = 15
case8.limit.cpu = 1
case8.limit.mem = 91224961
case8.diff.output.ignorespaces = true
#case8.limit.stdout = 8
#case8.command = "./h7/build/ex2"
case8.in = "case8.in"
case9.diff.output.score = 15
case9.limit.cpu = 1
case9.limit.mem = 91224961
case9.diff.output.ignorespaces = true
#case9.limit.stdout = 8
#case9.command = "./h7/build/ex2"
case9.in = "case9.in"

View File

@ -16,4 +16,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/tests/homework
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/tests/homework

View File

@ -18,4 +18,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/tests/homework" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/tests/homework" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"

View File

@ -16,4 +16,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/homework
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/homework

View File

@ -16,5 +16,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/tests/projects/p3
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/tests/projects/p3

View File

@ -18,5 +18,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/tests/projects/p3" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/tests/projects/p3" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"

View File

@ -16,5 +16,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/projects/p3
sudo -E -u tt joj3 -conf-root /home/tt/.config/joj/projects/p3

View File

@ -18,5 +18,4 @@ jobs:
fetch-depth: 0
- name: run joj3
run: |
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/projects/p3" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"
sudo -E -u tt joj3 -conf-root "/home/tt/.config/joj/projects/p3" -conf-name "conf-release.json" -tag "${{ github.ref_name }}"