diff --git a/README.md b/README.md index 98a94e8..07ca674 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,7 @@ $ # make sure you are in go-judge directory $ ./tmp/go-judge -http-addr 0.0.0.0:5050 -grpc-addr 0.0.0.0:5051 -monitor-addr 0.0.0.0:5052 -enable-grpc -enable-debug -enable-metrics ``` -6. Pull submodules. It might be slow, so only run it when necessary. +6. Pull submodules. It might be slow, so only run it when the test branches are out of date. ```bash $ # make sure you are in JOJ3 directory @@ -75,7 +75,7 @@ Check `Cmd` at <https://github.com/criyle/go-judge#rest-api-interface>. Some difference: -- `CopyInCwd bool`: set to `true` to add everything in the current working directory to `CopyIn`. +- `CopyInDir string`: set to non-empty string to add everything in that directory to `CopyIn`. - `CopyInCached map[string]string`: key: file name in the sandbox, value: file name used in `CopyOutCached`. - `LocalFile`: now supports the relative path @@ -88,6 +88,12 @@ Check the `Result` at <https://github.com/criyle/go-judge#rest-api-interface>. - `Score int`: score of the stage. - `Comment string`: comment on the stage. +## Binaries (under `/cmd` and `/pkg`) + +### Sample + +Just a sample on how to write an executable that can be called by the executor. + ### HealthCheck The repohealth check will return a json list to for check result. The structure follows the score-comment pattern. @@ -95,3 +101,53 @@ The repohealth check will return a json list to for check result. The structure HealthCheck currently includes, `reposize`, `forbidden file`, `Metafile existence`, `non-ascii character` in file and message, `release tag`, and `ci files invariance` check. The workflow is `joj3` pass cli args to healthcheck binary. See `./cmd/healthcheck/main.go` to view all flags. + +## Executors (under `/internal/executors`) + +### Dummy + +Do not execute any command. Just return empty `ExecutorResult` slice. + +### Sandbox + +Run the commands in `go-judge` and output the `ExecutorResult` slice. + +## Parsers (under `/internal/parsers`) + +### Clang Tidy + +Parser for `clang-tidy`, check `/examples/clangtidy` on how to call `clang-tidy` with proper parameters. + +### Cppcheck + +Parser for `cppcheck`, check `/examples/cppcheck` on how to call `cppcheck` with proper parameters. + +### Cpplint + +Parser for `cpplint`, check `/examples/cpplint` on how to call `cpplint` with proper parameters. + +### Diff + +Compare the specified output of `ExecutorResult` with the content of the answer file. If they are the same, then score will be given. Just like a normal online judge system. + +### Dummy + +Does not parse the output of `ExecutorResult`. It just output what is set inside the configuration file as score and comment. Currently it is used to output metadata for `joint-teapot`. + +In `joint-teapot`, it will take the content before `-` of the comment of the first stage with name `metadata` as the exercise name and record in the scoreboard. (e.g. If the comment is `p2-s2-0xdeadbeef`, then the exercise name is `p2`.) + +### Healthcheck + +Parser for the `healthcheck` binary mentioned before. + +### Keyword + +Match the given keyword from the specified output of `ExecutorResult`. For each match, a deduction of score is given. Can be useful if we do not have a specific parser for a code quality tool. Check `/examples/keyword`. + +### Result Status + +Only check if all the status of the executor is `StatusAccepted`. Can be used to check whether the command run in the executor exit normally. + +### Sample + +Parser for the `sample` binary mentioned before. Only used as a sample. diff --git a/cmd/joj3/conf.go b/cmd/joj3/conf.go index bb5f484..544c9d0 100644 --- a/cmd/joj3/conf.go +++ b/cmd/joj3/conf.go @@ -85,22 +85,6 @@ func parseConfFile(path string, jobtype JobType) (conf Conf, err error) { slog.Error("parse stages conf", "error", err) return } - - if err = d.Validate(&conf); err != nil { - slog.Error("validate stages conf", "error", err) - return - } - - filteredStages := []Stage{} - - for _, stage := range conf.Stages { - if filterStage(stage, jobtype) { - filteredStages = append(filteredStages, stage) - } - } - - conf.Stages = filteredStages - return } diff --git a/internal/executors/sandbox/convert.go b/internal/executors/sandbox/convert.go index 827dd15..c739f79 100644 --- a/internal/executors/sandbox/convert.go +++ b/internal/executors/sandbox/convert.go @@ -28,7 +28,7 @@ func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType { CpuSetLimit: c.CPUSetLimit, DataSegmentLimit: c.DataSegmentLimit, AddressSpaceLimit: c.AddressSpaceLimit, - CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInCwd), + CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInDir), CopyOut: convertPBCopyOut(c.CopyOut), CopyOutCached: convertPBCopyOut(c.CopyOutCached), CopyOutMax: c.CopyOutMax, @@ -39,9 +39,11 @@ func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType { return ret } -func convertPBCopyIn(copyIn map[string]stage.CmdFile, copyInCwd bool) map[string]*pb.Request_File { - if copyInCwd { - _ = filepath.Walk(".", +func convertPBCopyIn( + copyIn map[string]stage.CmdFile, copyInDir string, +) map[string]*pb.Request_File { + if copyInDir != "" { + _ = filepath.Walk(copyInDir, func(path string, info os.FileInfo, err error) error { if err != nil { return nil diff --git a/internal/parsers/cppcheck/score.go b/internal/parsers/cppcheck/score.go index d6028fb..dbdf81e 100644 --- a/internal/parsers/cppcheck/score.go +++ b/internal/parsers/cppcheck/score.go @@ -29,7 +29,7 @@ func severityFromString(severityString string) (Severity, error) { case "information": return INFORMATION, nil default: - return UNKNOWN, fmt.Errorf("unkown severity type \"%s\" for cppcheck", severityString) + return UNKNOWN, fmt.Errorf("unknown severity type \"%s\" for cppcheck", severityString) } } diff --git a/internal/stage/model.go b/internal/stage/model.go index dba945a..224b687 100644 --- a/internal/stage/model.go +++ b/internal/stage/model.go @@ -46,7 +46,7 @@ type Cmd struct { CopyIn map[string]CmdFile `json:"copyIn"` CopyInCached map[string]string `json:"copyInCached"` - CopyInCwd bool `json:"copyInCwd"` + CopyInDir string `json:"copyInDir"` CopyOut []string `json:"copyOut"` CopyOutCached []string `json:"copyOutCached"` diff --git a/pkg/healthcheck/commit.go b/pkg/healthcheck/commit.go index 8b1d579..375046e 100644 --- a/pkg/healthcheck/commit.go +++ b/pkg/healthcheck/commit.go @@ -7,7 +7,6 @@ import ( "unicode" "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing/object" ) // nonAsciiMsg checks for non-ASCII characters in the commit message. @@ -28,23 +27,19 @@ func NonAsciiMsg(root string) error { slog.Error("getting reference", "err", err) return fmt.Errorf("error getting reference: %v", err) } - commits, err := repo.Log(&git.LogOptions{From: ref.Hash()}) + + commit, err := repo.CommitObject(ref.Hash()) if err != nil { - slog.Error("getting commits", "err", err) - return fmt.Errorf("error getting commits from reference %s: %v", ref.Hash(), err) + slog.Error("getting latest commit", "err", err) + return fmt.Errorf("error getting latest commit: %v", err) } - var msgs []string - err = commits.ForEach(func(c *object.Commit) error { - msgs = append(msgs, c.Message) + msg := commit.Message + if msg == "" { return nil - }) - if err != nil { - slog.Error("iterating commits", "err", err) - return fmt.Errorf("error iterating commits: %v", err) } - var nonAsciiMsgs []string + var isCommitLegal bool = true // List of prefixes to ignore in the commit message ignoredPrefixes := []string{ "Co-authored-by:", @@ -53,35 +48,31 @@ func NonAsciiMsg(root string) error { "Reviewed-on:", } - for _, msg := range msgs { - if msg == "" { + // Split message by lines and ignore specific lines with prefixes + lines := strings.Split(msg, "\n") + for _, line := range lines { + trimmedLine := strings.TrimSpace(line) + ignore := false + for _, prefix := range ignoredPrefixes { + if strings.HasPrefix(trimmedLine, prefix) { + ignore = true + break + } + } + if ignore { continue } - // Split message by lines and ignore specific lines with prefixes - lines := strings.Split(msg, "\n") - for _, line := range lines { - trimmedLine := strings.TrimSpace(line) - ignore := false - for _, prefix := range ignoredPrefixes { - if strings.HasPrefix(trimmedLine, prefix) { - ignore = true - break - } - } - if ignore { - continue - } - // Check for non-ASCII characters in the rest of the lines - for _, c := range line { - if c > unicode.MaxASCII { - nonAsciiMsgs = append(nonAsciiMsgs, msg) - break - } + // Check for non-ASCII characters in the rest of the lines + for _, c := range line { + if c > unicode.MaxASCII { + isCommitLegal = false + break } } } - if len(nonAsciiMsgs) > 0 { - return fmt.Errorf("Non-ASCII characters in commit messages:\n%s", strings.Join(nonAsciiMsgs, "\n")) + + if !isCommitLegal { + return fmt.Errorf("Non-ASCII characters in commit messages:\n%s", msg) } return nil } diff --git a/pkg/healthcheck/meta.go b/pkg/healthcheck/meta.go index 2e78d50..a78da6b 100644 --- a/pkg/healthcheck/meta.go +++ b/pkg/healthcheck/meta.go @@ -25,7 +25,7 @@ func getMetas(rootDir string, fileList []string) ([]string, string, error) { matched := false umatchedRes := "" - // TODO: it seems that there is no good find subsitution now + // TODO: it seems that there is no good find substitution now // modify current code if exist a better solution for i, regex := range regexList { for _, file := range files { diff --git a/scripts/prepare_test_repos.sh b/scripts/prepare_test_repos.sh index c679ab4..270567e 100755 --- a/scripts/prepare_test_repos.sh +++ b/scripts/prepare_test_repos.sh @@ -18,14 +18,14 @@ for submodule in $submodules; do else cd $repo_dir git fetch --all - cd - + cd - > /dev/null fi fi repo_names[$repo_name]=1 cd $repo_dir git checkout -q $branch git reset -q --hard origin/$branch - cd - + cd - > /dev/null submodule_dir="$submodules_dir/$repo_name/$submodule" mkdir -p $submodule_dir cp -rT $repo_dir $submodule_dir diff --git a/scripts/run_foreach_test_repos.sh b/scripts/run_foreach_test_repos.sh index 6789f3e..9710f5b 100755 --- a/scripts/run_foreach_test_repos.sh +++ b/scripts/run_foreach_test_repos.sh @@ -17,5 +17,5 @@ for submodule in $submodules; do mv -f "joj3_result.json" "expected.json" fi fi - cd - + cd - > /dev/null done