Merge branch 'master' into commit-parser
Some checks failed
checks / build (push) Failing after 0s
checks / build (pull_request) Failing after 0s

This commit is contained in:
zzjc1234 2024-09-23 12:36:34 +08:00
commit 9d3a980272
9 changed files with 97 additions and 64 deletions

View File

@ -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 $ ./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 ```bash
$ # make sure you are in JOJ3 directory $ # 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: 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`. - `CopyInCached map[string]string`: key: file name in the sandbox, value: file name used in `CopyOutCached`.
- `LocalFile`: now supports the relative path - `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. - `Score int`: score of the stage.
- `Comment string`: comment on 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 ### HealthCheck
The repohealth check will return a json list to for check result. The structure follows the score-comment pattern. 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. 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. 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.

View File

@ -85,22 +85,6 @@ func parseConfFile(path string, jobtype JobType) (conf Conf, err error) {
slog.Error("parse stages conf", "error", err) slog.Error("parse stages conf", "error", err)
return 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 return
} }

View File

@ -28,7 +28,7 @@ func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType {
CpuSetLimit: c.CPUSetLimit, CpuSetLimit: c.CPUSetLimit,
DataSegmentLimit: c.DataSegmentLimit, DataSegmentLimit: c.DataSegmentLimit,
AddressSpaceLimit: c.AddressSpaceLimit, AddressSpaceLimit: c.AddressSpaceLimit,
CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInCwd), CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInDir),
CopyOut: convertPBCopyOut(c.CopyOut), CopyOut: convertPBCopyOut(c.CopyOut),
CopyOutCached: convertPBCopyOut(c.CopyOutCached), CopyOutCached: convertPBCopyOut(c.CopyOutCached),
CopyOutMax: c.CopyOutMax, CopyOutMax: c.CopyOutMax,
@ -39,9 +39,11 @@ func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType {
return ret return ret
} }
func convertPBCopyIn(copyIn map[string]stage.CmdFile, copyInCwd bool) map[string]*pb.Request_File { func convertPBCopyIn(
if copyInCwd { copyIn map[string]stage.CmdFile, copyInDir string,
_ = filepath.Walk(".", ) map[string]*pb.Request_File {
if copyInDir != "" {
_ = filepath.Walk(copyInDir,
func(path string, info os.FileInfo, err error) error { func(path string, info os.FileInfo, err error) error {
if err != nil { if err != nil {
return nil return nil

View File

@ -29,7 +29,7 @@ func severityFromString(severityString string) (Severity, error) {
case "information": case "information":
return INFORMATION, nil return INFORMATION, nil
default: default:
return UNKNOWN, fmt.Errorf("unkown severity type \"%s\" for cppcheck", severityString) return UNKNOWN, fmt.Errorf("unknown severity type \"%s\" for cppcheck", severityString)
} }
} }

View File

@ -46,7 +46,7 @@ type Cmd struct {
CopyIn map[string]CmdFile `json:"copyIn"` CopyIn map[string]CmdFile `json:"copyIn"`
CopyInCached map[string]string `json:"copyInCached"` CopyInCached map[string]string `json:"copyInCached"`
CopyInCwd bool `json:"copyInCwd"` CopyInDir string `json:"copyInDir"`
CopyOut []string `json:"copyOut"` CopyOut []string `json:"copyOut"`
CopyOutCached []string `json:"copyOutCached"` CopyOutCached []string `json:"copyOutCached"`

View File

@ -7,7 +7,6 @@ import (
"unicode" "unicode"
"github.com/go-git/go-git/v5" "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. // 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) slog.Error("getting reference", "err", err)
return fmt.Errorf("error getting reference: %v", 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 { if err != nil {
slog.Error("getting commits", "err", err) slog.Error("getting latest commit", "err", err)
return fmt.Errorf("error getting commits from reference %s: %v", ref.Hash(), err) return fmt.Errorf("error getting latest commit: %v", err)
} }
var msgs []string msg := commit.Message
err = commits.ForEach(func(c *object.Commit) error { if msg == "" {
msgs = append(msgs, c.Message)
return nil 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 // List of prefixes to ignore in the commit message
ignoredPrefixes := []string{ ignoredPrefixes := []string{
"Co-authored-by:", "Co-authored-by:",
@ -53,35 +48,31 @@ func NonAsciiMsg(root string) error {
"Reviewed-on:", "Reviewed-on:",
} }
for _, msg := range msgs { // Split message by lines and ignore specific lines with prefixes
if msg == "" { 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 continue
} }
// Split message by lines and ignore specific lines with prefixes // Check for non-ASCII characters in the rest of the lines
lines := strings.Split(msg, "\n") for _, c := range line {
for _, line := range lines { if c > unicode.MaxASCII {
trimmedLine := strings.TrimSpace(line) isCommitLegal = false
ignore := false break
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
}
} }
} }
} }
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 return nil
} }

View File

@ -25,7 +25,7 @@ func getMetas(rootDir string, fileList []string) ([]string, string, error) {
matched := false matched := false
umatchedRes := "" 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 // modify current code if exist a better solution
for i, regex := range regexList { for i, regex := range regexList {
for _, file := range files { for _, file := range files {

View File

@ -18,14 +18,14 @@ for submodule in $submodules; do
else else
cd $repo_dir cd $repo_dir
git fetch --all git fetch --all
cd - cd - > /dev/null
fi fi
fi fi
repo_names[$repo_name]=1 repo_names[$repo_name]=1
cd $repo_dir cd $repo_dir
git checkout -q $branch git checkout -q $branch
git reset -q --hard origin/$branch git reset -q --hard origin/$branch
cd - cd - > /dev/null
submodule_dir="$submodules_dir/$repo_name/$submodule" submodule_dir="$submodules_dir/$repo_name/$submodule"
mkdir -p $submodule_dir mkdir -p $submodule_dir
cp -rT $repo_dir $submodule_dir cp -rT $repo_dir $submodule_dir

View File

@ -17,5 +17,5 @@ for submodule in $submodules; do
mv -f "joj3_result.json" "expected.json" mv -f "joj3_result.json" "expected.json"
fi fi
fi fi
cd - cd - > /dev/null
done done