WIP: commit msg parser #39

Closed
周赵嘉程521432910016 wants to merge 24 commits from commit-parser into master

View File

@ -1,32 +1,45 @@
package main
import (
"fmt"
"log/slog"
"regexp"
"strings"
"focs.ji.sjtu.edu.cn/git/FOCS-dev/JOJ3/internal/stage"
"github.com/go-git/go-git/v5"
"github.com/koding/multiconfig"
)
type JobType int
const (
HC JobType = iota
CQ
OJ
)
type Stage struct {
Name string
Executor struct {
Name string
With struct {
Default stage.Cmd
Cases []OptionalCmd
}
}
Parser struct {
Name string
With interface{}
}
}
type Conf struct {
SandboxExecServer string `default:"localhost:5051"`
SandboxToken string `default:""`
LogLevel int `default:"0"`
OutputPath string `default:"joj3_result.json"`
Stages []struct {
Name string
Executor struct {
Name string
With struct {
Default stage.Cmd
Cases []OptionalCmd
}
}
Parser struct {
Name string
With interface{}
}
}
Stages []Stage
}
type OptionalCmd struct {
@ -60,40 +73,113 @@ type OptionalCmd struct {
AddressSpaceLimit *bool
}
func parseConfFile(path string) (conf Conf, err error) {
func parseConfFile(path string, jobtype JobType) (conf Conf, err error) {
d := &multiconfig.DefaultLoader{}
d.Loader = multiconfig.MultiLoader(
&multiconfig.TagLoader{},
&multiconfig.JSONLoader{Path: path},
)
d.Validator = multiconfig.MultiValidator(&multiconfig.RequiredValidator{})
if err = d.Load(&conf); err != nil {
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
}
func filterStage(stage Stage, jobtype JobType) bool {
switch jobtype {
case HC:
return stage.Name == "healthcheck"
case CQ:
return stage.Name == "compile" || stage.Name == "healthcheck"
case OJ:
return true
default:
return false
}
}
func validateHw(hw string) error {
matched, err := regexp.MatchString(`^hw[0-9]+$`, hw)
if err != nil {
return fmt.Errorf("error compiling regex: %w", err)
}
if !matched {
return fmt.Errorf("error: hw does not match the required pattern")
}
return nil
}
func commitMsgToConf() (conf Conf, err error) {
r, err := git.PlainOpen(".")
if err != nil {
return
}
ref, err := r.Head()
if err != nil {
return
}
commit, err := r.CommitObject(ref.Hash())
if err != nil {
return
}
file := "conf.json"
jobtype := HC
msg := commit.Message
slog.Debug("commit msg to conf", "msg", msg)
// TODO: parse msg to conf name
conf, err = parseConfFile("conf.json")
if msg == "" {
conf, err = parseConfFile(file, jobtype)
return
}
line := strings.Split(msg, "\n")[0]
words := strings.Fields(line)
head := words[0]
var hw string
if strings.HasSuffix(head, ":") || strings.HasSuffix(head, ".") {
head = head[:len(head)-1]
}
if len(words) == 3 {
hw = words[1]
if err = validateHw(hw); err != nil {
return
}
switch head {
case "feat", "fix", "refactor", "perf", "test", "build", "revert":
file = strings.Replace(file, "conf", "conf-"+hw, 1)
jobtype = CQ
case "joj", "grading":
file = strings.Replace(file, "conf", "conf-"+hw, 1)
jobtype = OJ
}
}
conf, err = parseConfFile(file, jobtype)
return
}