Compare commits

..

No commits in common. "a5767cf040c64c1c1e85f881a3aa9f92f01f94f8" and "762b1aa49df4c4966fa430f5f89877dd0559ba0a" have entirely different histories.

12 changed files with 115 additions and 239 deletions

View File

@ -3,9 +3,7 @@
BUILD_DIR = ./build BUILD_DIR = ./build
TMP_DIR = ./tmp TMP_DIR = ./tmp
APPS := $(notdir $(wildcard ./cmd/*)) APPS := $(notdir $(wildcard ./cmd/*))
COMMIT_HASH := $(shell git rev-parse --short HEAD) VERSION := $(shell git rev-parse --short HEAD)
DATE := $(shell date +"%Y%m%d-%H%M%S")
VERSION := $(COMMIT_HASH)-$(DATE)
FLAGS := "-s -w -X main.Version=$(VERSION)" FLAGS := "-s -w -X main.Version=$(VERSION)"
all: build all: build
@ -32,4 +30,4 @@ test:
ci-test: ci-test:
./scripts/prepare_test_repos.sh $(TMP_DIR) ./scripts/prepare_test_repos.sh $(TMP_DIR)
./scripts/run_foreach_test_repos.sh $(TMP_DIR) "sed -i '2i \ \ \"sandboxExecServer\": \"172.17.0.1:5051\",' conf.json" ./scripts/run_foreach_test_repos.sh $(TMP_DIR) "sed -i '2i \ \ \"sandboxExecServer\": \"172.17.0.1:5051\",' conf.json"
GITHUB_ACTIONS="test" go test -coverprofile cover.out -v ./... go test -coverprofile cover.out -v ./...

View File

@ -4,16 +4,12 @@
## Quick Start ## Quick Start
1. Clone this repo in a Linux computer. For Windows, use [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install). 1. Make sure you are in a Unix-like OS (Linux, MacOS). For Windows, use [WSL 2](https://learn.microsoft.com/en-us/windows/wsl/install).
```bash
$ git clone ssh://git@focs.ji.sjtu.edu.cn:2222/JOJ/JOJ3.git
```
2. Install [Go](https://go.dev/doc/install). Also, make sure `make` and `git` are installed and all 3 programs are presented in `$PATH`. 2. Install [Go](https://go.dev/doc/install). Also, make sure `make` and `git` are installed and all 3 programs are presented in `$PATH`.
- If you have problem on connecting to the Go website and Go packages, download Go from [studygolang](https://studygolang.com/dl) and run `go env -w GOPROXY=https://goproxy.io,direct` to set the Go modules mirror proxy after installing Go. - If you have problem on connecting to the Go website and Go packages, download Go from [studygolang](https://studygolang.com/dl) and run `go env -w GOPROXY=https://goproxy.io,direct` to set the Go modules mirror proxy after installing Go.
3. Enable cgroup v2 for your OS. For WSL2, check [here](https://stackoverflow.com/a/73376219/13724598). So that you do not need root permission to run `go-judge`. 3. Enable cgroup v2 for your OS. Check [here](https://stackoverflow.com/a/73376219/13724598). So that you do not need root permission to run `go-judge`.
4. Clone [go-judge](https://github.com/criyle/go-judge). 4. Clone [go-judge](https://github.com/criyle/go-judge).

View File

@ -13,48 +13,16 @@ import (
"github.com/koding/multiconfig" "github.com/koding/multiconfig"
) )
type ConfStage struct {
Name string
Group string
Executor struct {
Name string
With struct {
Default stage.Cmd
Cases []OptionalCmd
}
}
Parsers []struct {
Name string
With interface{}
}
}
type Conf struct { type Conf struct {
Name string `default:"unknown"`
LogPath string `default:""`
Stage struct {
SandboxExecServer string `default:"localhost:5051"`
SandboxToken string `default:""`
OutputPath string `default:"joj3_result.json"`
Stages []ConfStage
}
Teapot struct {
LogPath string `default:"/home/tt/.cache/joint-teapot-debug.log"`
ScoreboardPath string `default:"scoreboard.csv"`
FailedTablePath string `default:"failed-table.md"`
GradingRepoName string `default:""`
SkipIssue bool `default:"false"`
SkipScoreboard bool `default:"false"`
SkipFailedTable bool `default:"false"`
}
// TODO: remove the following backward compatibility fields
SandboxExecServer string `default:"localhost:5051"` SandboxExecServer string `default:"localhost:5051"`
SandboxToken string `default:""` SandboxToken string `default:""`
LogPath string `default:""`
OutputPath string `default:"joj3_result.json"` OutputPath string `default:"joj3_result.json"`
GradingRepoName string `default:""` GradingRepoName string `default:""`
SkipTeapot bool `default:"true"` SkipTeapot bool `default:"true"`
ScoreboardPath string `default:"scoreboard.csv"` ScoreboardPath string `default:"scoreboard.csv"`
FailedTablePath string `default:"failed-table.md"` FailedTablePath string `default:"failed-table.md"`
Name string `default:"unknown"`
Stages []struct { Stages []struct {
Name string Name string
Group string Group string
@ -144,55 +112,25 @@ func parseConventionalCommit(commit string) (*ConventionalCommit, error) {
return cc, nil return cc, nil
} }
func ParseConfFile(path string) (conf *Conf, err error) { func parseConfFile(path string) (conf Conf, err error) {
conf = new(Conf)
d := &multiconfig.DefaultLoader{} d := &multiconfig.DefaultLoader{}
d.Loader = multiconfig.MultiLoader( d.Loader = multiconfig.MultiLoader(
&multiconfig.TagLoader{}, &multiconfig.TagLoader{},
&multiconfig.JSONLoader{Path: path}, &multiconfig.JSONLoader{Path: path},
) )
d.Validator = multiconfig.MultiValidator(&multiconfig.RequiredValidator{}) d.Validator = multiconfig.MultiValidator(&multiconfig.RequiredValidator{})
if err = d.Load(conf); err != nil { if err = d.Load(&conf); err != nil {
slog.Error("parse stages conf", "error", err) slog.Error("parse stages conf", "error", err)
return return
} }
if err = d.Validate(conf); err != nil { if err = d.Validate(&conf); err != nil {
slog.Error("validate stages conf", "error", err) slog.Error("validate stages conf", "error", err)
return return
} }
// TODO: remove the following backward compatibility codes
if len(conf.Stage.Stages) == 0 {
conf.Stage.SandboxExecServer = conf.SandboxExecServer
conf.Stage.SandboxToken = conf.SandboxToken
conf.Stage.OutputPath = conf.OutputPath
conf.Stage.Stages = make([]ConfStage, len(conf.Stages))
for i, stage := range conf.Stages {
conf.Stage.Stages[i].Name = stage.Name
conf.Stage.Stages[i].Group = stage.Group
conf.Stage.Stages[i].Executor = stage.Executor
conf.Stage.Stages[i].Parsers = []struct {
Name string
With interface{}
}{
{
Name: stage.Parser.Name,
With: stage.Parser.With,
},
}
}
conf.Teapot.GradingRepoName = conf.GradingRepoName
conf.Teapot.ScoreboardPath = conf.ScoreboardPath
conf.Teapot.FailedTablePath = conf.FailedTablePath
if conf.SkipTeapot {
conf.Teapot.SkipScoreboard = true
conf.Teapot.SkipFailedTable = true
conf.Teapot.SkipIssue = true
}
}
return return
} }
func ParseMsg(confRoot, confName, msg string) (confPath, group string, err error) { func ParseMsg(confRoot, confName, msg string) (conf Conf, group string, err error) {
slog.Info("parse msg", "msg", msg) slog.Info("parse msg", "msg", msg)
conventionalCommit, err := parseConventionalCommit(msg) conventionalCommit, err := parseConventionalCommit(msg)
if err != nil { if err != nil {
@ -200,7 +138,7 @@ func ParseMsg(confRoot, confName, msg string) (confPath, group string, err error
} }
slog.Info("conventional commit", "commit", conventionalCommit) slog.Info("conventional commit", "commit", conventionalCommit)
confRoot = filepath.Clean(confRoot) confRoot = filepath.Clean(confRoot)
confPath = filepath.Clean(fmt.Sprintf("%s/%s/%s", confPath := filepath.Clean(fmt.Sprintf("%s/%s/%s",
confRoot, conventionalCommit.Scope, confName)) confRoot, conventionalCommit.Scope, confName))
relPath, err := filepath.Rel(confRoot, confPath) relPath, err := filepath.Rel(confRoot, confPath)
if err != nil { if err != nil {
@ -210,6 +148,11 @@ func ParseMsg(confRoot, confName, msg string) (confPath, group string, err error
err = fmt.Errorf("invalid scope as path: %s", conventionalCommit.Scope) err = fmt.Errorf("invalid scope as path: %s", conventionalCommit.Scope)
return return
} }
slog.Info("try to load conf", "path", confPath)
conf, err = parseConfFile(confPath)
if err != nil {
return
}
groupKeywords := []string{"joj"} groupKeywords := []string{"joj"}
for _, groupKeyword := range groupKeywords { for _, groupKeyword := range groupKeywords {
if strings.Contains( if strings.Contains(
@ -218,6 +161,7 @@ func ParseMsg(confRoot, confName, msg string) (confPath, group string, err error
break break
} }
} }
slog.Debug("conf loaded", "conf", conf)
return return
} }

View File

@ -45,7 +45,7 @@ func mainImpl() error {
return err return err
} }
} }
confPath, group, err := conf.ParseMsg(confRoot, confName, msg) confObj, group, err := conf.ParseMsg(confRoot, confName, msg)
if err != nil { if err != nil {
slog.Error("parse msg", "error", err) slog.Error("parse msg", "error", err)
validScopes, scopeErr := conf.ListValidScopes( validScopes, scopeErr := conf.ListValidScopes(
@ -58,13 +58,6 @@ func mainImpl() error {
"valid scopes", validScopes) "valid scopes", validScopes)
return err return err
} }
slog.Info("try to load conf", "path", confPath)
confObj, err := conf.ParseConfFile(confPath)
if err != nil {
slog.Error("parse conf", "error", err)
return err
}
slog.Debug("conf loaded", "conf", confObj)
if err := setupSlog(confObj.LogPath); err != nil { // after conf is loaded if err := setupSlog(confObj.LogPath); err != nil { // after conf is loaded
slog.Error("setup slog", "error", err) slog.Error("setup slog", "error", err)
return err return err

View File

@ -13,10 +13,10 @@ import (
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
) )
func generateStages(conf *conf.Conf, group string) ([]stage.Stage, error) { func generateStages(conf conf.Conf, group string) ([]stage.Stage, error) {
stages := []stage.Stage{} stages := []stage.Stage{}
existNames := map[string]bool{} existNames := map[string]bool{}
for _, s := range conf.Stage.Stages { for _, s := range conf.Stages {
if s.Group != "" && group != s.Group { if s.Group != "" && group != s.Group {
continue continue
} }
@ -50,20 +50,12 @@ func generateStages(conf *conf.Conf, group string) ([]stage.Stage, error) {
if len(s.Executor.With.Cases) == 0 { if len(s.Executor.With.Cases) == 0 {
cmds = []stage.Cmd{defaultCmd} cmds = []stage.Cmd{defaultCmd}
} }
parsers := []stage.StageParser{}
for _, p := range s.Parsers {
parsers = append(parsers, stage.StageParser{
Name: p.Name,
Conf: p.With,
})
}
stages = append(stages, stage.Stage{ stages = append(stages, stage.Stage{
Name: s.Name, Name: s.Name,
Executor: stage.StageExecutor{ ExecutorName: s.Executor.Name,
Name: s.Executor.Name, ExecutorCmds: cmds,
Cmds: cmds, ParserName: s.Parser.Name,
}, ParserConf: s.Parser.With,
Parsers: parsers,
}) })
} }
slog.Debug("stages generated", "stages", stages) slog.Debug("stages generated", "stages", stages)
@ -81,11 +73,8 @@ func outputResult(outputPath string, results []stage.StageResult) error {
append(content, []byte("\n")...), 0o600) append(content, []byte("\n")...), 0o600)
} }
func Run(conf *conf.Conf, group string) error { func Run(conf conf.Conf, group string) error {
executors.InitWithConf( executors.InitWithConf(conf.SandboxExecServer, conf.SandboxToken)
conf.Stage.SandboxExecServer,
conf.Stage.SandboxToken,
)
stages, err := generateStages(conf, group) stages, err := generateStages(conf, group)
if err != nil { if err != nil {
slog.Error("generate stages", "error", err) slog.Error("generate stages", "error", err)
@ -97,7 +86,7 @@ func Run(conf *conf.Conf, group string) error {
slog.Error("run stages", "error", err) slog.Error("run stages", "error", err)
return err return err
} }
if err := outputResult(conf.Stage.OutputPath, results); err != nil { if err := outputResult(conf.OutputPath, results); err != nil {
slog.Error("output result", "error", err) slog.Error("output result", "error", err)
return err return err
} }

View File

@ -7,22 +7,17 @@ import (
"os/exec" "os/exec"
"regexp" "regexp"
"strings" "strings"
"sync"
"github.com/joint-online-judge/JOJ3/cmd/joj3/conf" "github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
) )
func Run(conf *conf.Conf) error { func Run(conf conf.Conf) error {
actions := os.Getenv("GITHUB_ACTIONS") if conf.SkipTeapot {
if actions != "true" {
slog.Info("teapot exit", "GITHUB_ACTIONS", actions)
return nil return nil
} }
os.Setenv("LOG_FILE_PATH", conf.Teapot.LogPath) os.Setenv("LOG_FILE_PATH", "/home/tt/.cache/joint-teapot-debug.log")
os.Setenv("_TYPER_STANDARD_TRACEBACK", "1") os.Setenv("_TYPER_STANDARD_TRACEBACK", "1")
envFilePath := "/home/tt/.config/teapot/teapot.env" envFilePath := "/home/tt/.config/teapot/teapot.env"
// TODO: pass sha to joint-teapot
// sha := os.Getenv("GITHUB_SHA")
actor := os.Getenv("GITHUB_ACTOR") actor := os.Getenv("GITHUB_ACTOR")
repository := os.Getenv("GITHUB_REPOSITORY") repository := os.Getenv("GITHUB_REPOSITORY")
runNumber := os.Getenv("GITHUB_RUN_NUMBER") runNumber := os.Getenv("GITHUB_RUN_NUMBER")
@ -34,61 +29,49 @@ func Run(conf *conf.Conf) error {
repoParts := strings.Split(repository, "/") repoParts := strings.Split(repository, "/")
repoName := repoParts[1] repoName := repoParts[1]
re := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`) re := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
execCommand := func(name string, cmdArgs []string) error { cmd := exec.Command("joint-teapot", "joj3-scoreboard",
cmd := exec.Command(name, cmdArgs...) // #nosec G204 envFilePath, conf.OutputPath, actor, conf.GradingRepoName, repoName,
outputBytes, err := cmd.CombinedOutput() runNumber, conf.ScoreboardPath, conf.Name) // #nosec G204
output := re.ReplaceAllString(string(outputBytes), "") outputBytes, err := cmd.CombinedOutput()
for _, line := range strings.Split(output, "\n") { output := re.ReplaceAllString(string(outputBytes), "")
if line == "" { for _, line := range strings.Split(output, "\n") {
continue if line == "" {
} continue
slog.Info(fmt.Sprintf("%s %s", name, cmdArgs[0]), "output", line)
} }
slog.Info("joint-teapot joj3-scoreboard", "output", line)
}
if err != nil {
slog.Error("joint-teapot joj3-scoreboard", "err", err)
return err return err
} }
var wg sync.WaitGroup cmd = exec.Command("joint-teapot", "joj3-failed-table",
var scoreboardErr, failedTableErr, issueErr error envFilePath, conf.OutputPath, actor, conf.GradingRepoName, repoName,
wg.Add(2) runNumber, conf.FailedTablePath, conf.Name) // #nosec G204
go func() { outputBytes, err = cmd.CombinedOutput()
defer wg.Done() output = re.ReplaceAllString(string(outputBytes), "")
if !conf.Teapot.SkipScoreboard { for _, line := range strings.Split(output, "\n") {
err := execCommand("joint-teapot", []string{ if line == "" {
"joj3-scoreboard", envFilePath, conf.Stage.OutputPath, actor, continue
conf.Teapot.GradingRepoName, repoName, runNumber,
conf.Teapot.ScoreboardPath, conf.Name,
})
if err != nil {
scoreboardErr = err
}
} }
if !conf.Teapot.SkipFailedTable { slog.Info("joint-teapot joj3-failed-table", "output", line)
err := execCommand("joint-teapot", []string{ }
"joj3-failed-table", envFilePath, conf.Stage.OutputPath, actor, if err != nil {
conf.Teapot.GradingRepoName, repoName, runNumber, slog.Error("joint-teapot joj3-failed-table", "err", err)
conf.Teapot.FailedTablePath, conf.Name, return err
}) }
if err != nil { cmd = exec.Command("joint-teapot", "joj3-create-result-issue",
failedTableErr = err envFilePath, conf.OutputPath, repoName, runNumber, conf.Name) // #nosec G204
} outputBytes, err = cmd.CombinedOutput()
output = re.ReplaceAllString(string(outputBytes), "")
for _, line := range strings.Split(output, "\n") {
if line == "" {
continue
} }
}() slog.Info("joint-teapot joj3-create-result-issue", "output", line)
go func() { }
defer wg.Done() if err != nil {
if !conf.Teapot.SkipIssue { slog.Error("joint-teapot joj3-create-result-issue", "err", err)
err := execCommand("joint-teapot", []string{ return err
"joj3-create-result-issue", envFilePath, conf.Stage.OutputPath,
repoName, runNumber, conf.Name,
})
if err != nil {
issueErr = err
}
}
}()
wg.Wait()
if scoreboardErr != nil || failedTableErr != nil || issueErr != nil {
slog.Error("teapot exit", "scoreboardErr", scoreboardErr,
"failedTableErr", failedTableErr, "issueErr", issueErr)
return fmt.Errorf("teapot exit")
} }
return nil return nil
} }

View File

@ -44,7 +44,6 @@ func main() {
checkRelease := flag.Bool("checkRelease", true, "trigger release check") checkRelease := flag.Bool("checkRelease", true, "trigger release check")
rootDir := flag.String("root", "", "") rootDir := flag.String("root", "", "")
repo := flag.String("repo", "", "") repo := flag.String("repo", "", "")
size := flag.Float64("reposize", 2, "size of the repo")
localList := flag.String("localList", "", "") localList := flag.String("localList", "", "")
droneBranch := flag.String("droneBranch", "", "") droneBranch := flag.String("droneBranch", "", "")
releaseCategories := flag.String("releaseCategories", "", "") releaseCategories := flag.String("releaseCategories", "", "")
@ -60,7 +59,7 @@ func main() {
} }
setupSlog() setupSlog()
var err error var err error
err = healthcheck.RepoSize(*size) err = healthcheck.RepoSize()
if err != nil { if err != nil {
fmt.Printf("### Repo Size Check Failed:\n%s\n", err.Error()) fmt.Printf("### Repo Size Check Failed:\n%s\n", err.Error())
} }

View File

@ -21,9 +21,7 @@ const (
) )
type Conf struct { type Conf struct {
PassComment string `default:"🥳Passed!\n"` Cases []struct {
FailComment string `default:"🧐Failed...\n"`
Cases []struct {
IgnoreResultStatus bool IgnoreResultStatus bool
Outputs []struct { Outputs []struct {
Score int Score int
@ -74,9 +72,9 @@ func (*Diff) Run(results []stage.ExecutorResult, confAny any) (
if compareChars(string(answer), result.Files[output.FileName], if compareChars(string(answer), result.Files[output.FileName],
output.CompareSpace) { output.CompareSpace) {
score += output.Score score += output.Score
comment += conf.PassComment comment += "Pass!\n"
} else { } else {
comment += conf.FailComment comment += "Fail!\n"
comment += fmt.Sprintf("Difference found in `%s`.\n", comment += fmt.Sprintf("Difference found in `%s`.\n",
output.FileName) output.FileName)
if !output.AlwaysHide { if !output.AlwaysHide {

View File

@ -29,27 +29,27 @@ func (*ResultDetail) Run(results []stage.ExecutorResult, confAny any) (
var res []stage.ParserResult var res []stage.ParserResult
for _, result := range results { for _, result := range results {
comment := "" comment := ""
// TODO: more human readable units
if conf.ShowExitStatus { if conf.ShowExitStatus {
comment += fmt.Sprintf("Exit Status: `%d`\n", result.ExitStatus) comment += fmt.Sprintf("Exit Status: %d\n", result.ExitStatus)
} }
if conf.ShowError { if conf.ShowError {
comment += fmt.Sprintf("Error: `%s`\n", result.Error) comment += fmt.Sprintf("Error: %s\n", result.Error)
} }
if conf.ShowTime { if conf.ShowTime {
comment += fmt.Sprintf("Time: `%d ms`\n", result.Time/1e9) comment += fmt.Sprintf("Time: %d\n", result.Time)
} }
if conf.ShowMemory { if conf.ShowMemory {
comment += fmt.Sprintf("Memory: `%.2f MiB`\n", comment += fmt.Sprintf("Memory: %d\n", result.Memory)
float64(result.Memory)/(1024*1024))
} }
if conf.ShowRunTime { if conf.ShowRunTime {
comment += fmt.Sprintf("RunTime: `%d ms`\n", result.RunTime/1e9) comment += fmt.Sprintf("RunTime: %d\n", result.RunTime)
} }
for _, file := range conf.ShowFiles { for _, file := range conf.ShowFiles {
content, ok := result.Files[file] content, ok := result.Files[file]
comment += fmt.Sprintf("File `%s`:\n", file) comment += fmt.Sprintf("File: `%s`.\n", file)
if ok { if ok {
comment += fmt.Sprintf("```\n%s\n```\n", content) comment += fmt.Sprintf("```%s```\n", content)
} else { } else {
comment += "Not found.\n" comment += "Not found.\n"
} }

View File

@ -150,19 +150,12 @@ func (r ExecutorResult) String() string {
return fmt.Sprintf("%+v", d) return fmt.Sprintf("%+v", d)
} }
type StageExecutor struct {
Name string
Cmds []Cmd
}
type StageParser struct {
Name string
Conf any
}
type Stage struct { type Stage struct {
Name string Name string
Executor StageExecutor ExecutorName string
Parsers []StageParser ExecutorCmds []Cmd
ParserName string
ParserConf any
} }
type ParserResult struct { type ParserResult struct {

View File

@ -8,68 +8,51 @@ import (
func Run(stages []Stage) (stageResults []StageResult, err error) { func Run(stages []Stage) (stageResults []StageResult, err error) {
var executorResults []ExecutorResult var executorResults []ExecutorResult
var parserResults []ParserResult var parserResults []ParserResult
var tmpParserResults []ParserResult
var forceQuit bool var forceQuit bool
slog.Info("stage run start") slog.Info("stage run start")
for _, stage := range stages { for _, stage := range stages {
slog.Info("stage start", "name", stage.Name) slog.Info("stage start", "name", stage.Name)
slog.Info("executor run start", "name", stage.Executor.Name) slog.Info("executor run start", "name", stage.ExecutorName)
slog.Debug("executor run start", "name", stage.Executor.Name, slog.Debug("executor run start", "name", stage.ExecutorName,
"cmds", stage.Executor.Cmds) "cmds", stage.ExecutorCmds)
executor, ok := executorMap[stage.Executor.Name] executor, ok := executorMap[stage.ExecutorName]
if !ok { if !ok {
slog.Error("executor not found", "name", stage.Executor.Name) slog.Error("executor not found", "name", stage.ExecutorName)
err = fmt.Errorf("executor not found: %s", stage.Executor.Name) err = fmt.Errorf("executor not found: %s", stage.ExecutorName)
return return
} }
executorResults, err = executor.Run(stage.Executor.Cmds) executorResults, err = executor.Run(stage.ExecutorCmds)
if err != nil { if err != nil {
slog.Error("executor run error", "name", stage.Executor.Name, "error", err) slog.Error("executor run error", "name", stage.ExecutorName, "error", err)
return return
} }
slog.Debug("executor run done", "results", executorResults) slog.Debug("executor run done", "results", executorResults)
for _, executorResult := range executorResults { for _, executorResult := range executorResults {
slog.Debug("executor run done", "result.Files", executorResult.Files) slog.Debug("executor run done", "result.Files", executorResult.Files)
} }
parserResults = []ParserResult{} slog.Info("parser run start", "name", stage.ParserName)
stageForceQuit := false slog.Debug("parser run start", "name", stage.ParserName,
for _, stageParser := range stage.Parsers { "conf", stage.ParserConf)
slog.Info("parser run start", "name", stageParser.Name) parser, ok := parserMap[stage.ParserName]
slog.Debug("parser run start", "name", stageParser.Name, if !ok {
"conf", stageParser.Conf) slog.Error("parser not found", "name", stage.ParserName)
parser, ok := parserMap[stageParser.Name] err = fmt.Errorf("parser not found: %s", stage.ParserName)
if !ok { return
slog.Error("parser not found", "name", stageParser.Name)
err = fmt.Errorf("parser not found: %s", stageParser.Name)
return
}
tmpParserResults, forceQuit, err = parser.Run(
executorResults, stageParser.Conf)
if err != nil {
slog.Error("parser run error", "name", stageParser.Name, "error", err)
return
}
stageForceQuit = stageForceQuit || forceQuit
slog.Debug("parser run done", "results", tmpParserResults)
if len(parserResults) == 0 {
parserResults = tmpParserResults
} else {
for i := range len(parserResults) {
parserResults[i].Score += tmpParserResults[i].Score
parserResults[i].Comment += tmpParserResults[i].Comment
}
}
if forceQuit {
slog.Error("parser force quit", "name", stageParser.Name)
}
} }
parserResults, forceQuit, err = parser.Run(executorResults, stage.ParserConf)
if err != nil {
slog.Error("parser run error", "name", stage.ParserName, "error", err)
return
}
slog.Debug("parser run done", "results", parserResults)
stageResults = append(stageResults, StageResult{ stageResults = append(stageResults, StageResult{
Name: stage.Name, Name: stage.Name,
Results: parserResults, Results: parserResults,
ForceQuit: stageForceQuit, ForceQuit: forceQuit,
}) })
if stageForceQuit { if forceQuit {
break slog.Error("parser force quit", "name", stage.ParserName)
return
} }
} }
return return

View File

@ -10,7 +10,7 @@ import (
// RepoSize checks the size of the repository to determine if it is oversized. // RepoSize checks the size of the repository to determine if it is oversized.
// It executes the 'git count-objects -v' command to obtain the size information, // It executes the 'git count-objects -v' command to obtain the size information,
func RepoSize(confSize float64) error { func RepoSize() error {
// TODO: reimplement here when go-git is available // TODO: reimplement here when go-git is available
// https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md // https://github.com/go-git/go-git/blob/master/COMPATIBILITY.md
cmd := exec.Command("git", "count-objects", "-v") cmd := exec.Command("git", "count-objects", "-v")
@ -33,8 +33,8 @@ func RepoSize(confSize float64) error {
sum += size sum += size
} }
} }
if sum > int(confSize*1024) { if sum > 2048 {
return fmt.Errorf("Repository larger than %.1f MiB. Please clean up or contact the teaching team.", confSize) return fmt.Errorf("Repository larger than 2MB. Please clean up or contact the teaching team.")
} }
return nil return nil
} }