refactor(cmd/joj3)!: conf #51
2
Makefile
2
Makefile
|
@ -30,4 +30,4 @@ test:
|
|||
ci-test:
|
||||
./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"
|
||||
go test -coverprofile cover.out -v ./...
|
||||
GITHUB_ACTIONS="test" go test -coverprofile cover.out -v ./...
|
||||
|
|
|
@ -13,16 +13,48 @@ import (
|
|||
"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 {
|
||||
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"`
|
||||
SandboxToken string `default:""`
|
||||
LogPath string `default:""`
|
||||
OutputPath string `default:"joj3_result.json"`
|
||||
GradingRepoName string `default:""`
|
||||
SkipTeapot bool `default:"true"`
|
||||
ScoreboardPath string `default:"scoreboard.csv"`
|
||||
FailedTablePath string `default:"failed-table.md"`
|
||||
Name string `default:"unknown"`
|
||||
Stages []struct {
|
||||
Name string
|
||||
Group string
|
||||
|
@ -127,6 +159,27 @@ func parseConfFile(path string) (conf Conf, err error) {
|
|||
slog.Error("validate stages conf", "error", err)
|
||||
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,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import (
|
|||
func generateStages(conf conf.Conf, group string) ([]stage.Stage, error) {
|
||||
stages := []stage.Stage{}
|
||||
existNames := map[string]bool{}
|
||||
for _, s := range conf.Stages {
|
||||
for _, s := range conf.Stage.Stages {
|
||||
if s.Group != "" && group != s.Group {
|
||||
continue
|
||||
}
|
||||
|
@ -50,12 +50,20 @@ func generateStages(conf conf.Conf, group string) ([]stage.Stage, error) {
|
|||
if len(s.Executor.With.Cases) == 0 {
|
||||
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{
|
||||
Name: s.Name,
|
||||
ExecutorName: s.Executor.Name,
|
||||
ExecutorCmds: cmds,
|
||||
ParserName: s.Parser.Name,
|
||||
ParserConf: s.Parser.With,
|
||||
Name: s.Name,
|
||||
Executor: stage.StageExecutor{
|
||||
Name: s.Executor.Name,
|
||||
Cmds: cmds,
|
||||
},
|
||||
Parsers: parsers,
|
||||
})
|
||||
}
|
||||
slog.Debug("stages generated", "stages", stages)
|
||||
|
@ -74,7 +82,10 @@ func outputResult(outputPath string, results []stage.StageResult) error {
|
|||
}
|
||||
|
||||
func Run(conf conf.Conf, group string) error {
|
||||
executors.InitWithConf(conf.SandboxExecServer, conf.SandboxToken)
|
||||
executors.InitWithConf(
|
||||
conf.Stage.SandboxExecServer,
|
||||
conf.Stage.SandboxToken,
|
||||
)
|
||||
stages, err := generateStages(conf, group)
|
||||
if err != nil {
|
||||
slog.Error("generate stages", "error", err)
|
||||
|
@ -86,7 +97,7 @@ func Run(conf conf.Conf, group string) error {
|
|||
slog.Error("run stages", "error", err)
|
||||
return err
|
||||
}
|
||||
if err := outputResult(conf.OutputPath, results); err != nil {
|
||||
if err := outputResult(conf.Stage.OutputPath, results); err != nil {
|
||||
slog.Error("output result", "error", err)
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -12,12 +12,16 @@ import (
|
|||
)
|
||||
|
||||
func Run(conf conf.Conf) error {
|
||||
if conf.SkipTeapot {
|
||||
actions := os.Getenv("GITHUB_ACTIONS")
|
||||
if actions != "true" {
|
||||
slog.Info("teapot exit", "GITHUB_ACTIONS", actions)
|
||||
return nil
|
||||
}
|
||||
os.Setenv("LOG_FILE_PATH", "/home/tt/.cache/joint-teapot-debug.log")
|
||||
os.Setenv("LOG_FILE_PATH", conf.Teapot.LogPath)
|
||||
os.Setenv("_TYPER_STANDARD_TRACEBACK", "1")
|
||||
envFilePath := "/home/tt/.config/teapot/teapot.env"
|
||||
// TODO: pass sha to joint-teapot
|
||||
// sha := os.Getenv("GITHUB_SHA")
|
||||
actor := os.Getenv("GITHUB_ACTOR")
|
||||
repository := os.Getenv("GITHUB_REPOSITORY")
|
||||
runNumber := os.Getenv("GITHUB_RUN_NUMBER")
|
||||
|
@ -29,49 +33,55 @@ func Run(conf conf.Conf) error {
|
|||
repoParts := strings.Split(repository, "/")
|
||||
repoName := repoParts[1]
|
||||
re := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
|
||||
cmd := exec.Command("joint-teapot", "joj3-scoreboard",
|
||||
envFilePath, conf.OutputPath, actor, conf.GradingRepoName, repoName,
|
||||
runNumber, conf.ScoreboardPath, conf.Name) // #nosec G204
|
||||
outputBytes, err := cmd.CombinedOutput()
|
||||
output := re.ReplaceAllString(string(outputBytes), "")
|
||||
for _, line := range strings.Split(output, "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
if !conf.Teapot.SkipScoreboard {
|
||||
cmd := exec.Command("joint-teapot", "joj3-scoreboard",
|
||||
envFilePath, conf.Stage.OutputPath, actor, conf.Teapot.GradingRepoName,
|
||||
repoName, runNumber, conf.Teapot.ScoreboardPath, 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-scoreboard", "output", line)
|
||||
}
|
||||
slog.Info("joint-teapot joj3-scoreboard", "output", line)
|
||||
}
|
||||
if err != nil {
|
||||
slog.Error("joint-teapot joj3-scoreboard", "err", err)
|
||||
return err
|
||||
}
|
||||
cmd = exec.Command("joint-teapot", "joj3-failed-table",
|
||||
envFilePath, conf.OutputPath, actor, conf.GradingRepoName, repoName,
|
||||
runNumber, conf.FailedTablePath, conf.Name) // #nosec G204
|
||||
outputBytes, err = cmd.CombinedOutput()
|
||||
output = re.ReplaceAllString(string(outputBytes), "")
|
||||
for _, line := range strings.Split(output, "\n") {
|
||||
if line == "" {
|
||||
continue
|
||||
if err != nil {
|
||||
slog.Error("joint-teapot joj3-scoreboard", "err", err)
|
||||
return err
|
||||
}
|
||||
slog.Info("joint-teapot joj3-failed-table", "output", line)
|
||||
}
|
||||
if err != nil {
|
||||
slog.Error("joint-teapot joj3-failed-table", "err", err)
|
||||
return err
|
||||
}
|
||||
cmd = exec.Command("joint-teapot", "joj3-create-result-issue",
|
||||
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
|
||||
if !conf.Teapot.SkipFailedTable {
|
||||
cmd := exec.Command("joint-teapot", "joj3-failed-table",
|
||||
envFilePath, conf.Stage.OutputPath, actor, conf.Teapot.GradingRepoName,
|
||||
repoName, runNumber, conf.Teapot.FailedTablePath, 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-failed-table", "output", line)
|
||||
}
|
||||
if err != nil {
|
||||
slog.Error("joint-teapot joj3-failed-table", "err", err)
|
||||
return err
|
||||
}
|
||||
slog.Info("joint-teapot joj3-create-result-issue", "output", line)
|
||||
}
|
||||
if err != nil {
|
||||
slog.Error("joint-teapot joj3-create-result-issue", "err", err)
|
||||
return err
|
||||
if !conf.Teapot.SkipIssue {
|
||||
cmd := exec.Command("joint-teapot", "joj3-create-result-issue",
|
||||
envFilePath, conf.Stage.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)
|
||||
}
|
||||
if err != nil {
|
||||
slog.Error("joint-teapot joj3-create-result-issue", "err", err)
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -150,12 +150,19 @@ func (r ExecutorResult) String() string {
|
|||
return fmt.Sprintf("%+v", d)
|
||||
}
|
||||
|
||||
type StageExecutor struct {
|
||||
Name string
|
||||
Cmds []Cmd
|
||||
}
|
||||
type StageParser struct {
|
||||
Name string
|
||||
Conf any
|
||||
}
|
||||
|
||||
type Stage struct {
|
||||
Name string
|
||||
ExecutorName string
|
||||
ExecutorCmds []Cmd
|
||||
ParserName string
|
||||
ParserConf any
|
||||
Name string
|
||||
Executor StageExecutor
|
||||
Parsers []StageParser
|
||||
}
|
||||
|
||||
type ParserResult struct {
|
||||
|
|
|
@ -8,51 +8,68 @@ import (
|
|||
func Run(stages []Stage) (stageResults []StageResult, err error) {
|
||||
var executorResults []ExecutorResult
|
||||
var parserResults []ParserResult
|
||||
var tmpParserResults []ParserResult
|
||||
var forceQuit bool
|
||||
slog.Info("stage run start")
|
||||
for _, stage := range stages {
|
||||
slog.Info("stage start", "name", stage.Name)
|
||||
slog.Info("executor run start", "name", stage.ExecutorName)
|
||||
slog.Debug("executor run start", "name", stage.ExecutorName,
|
||||
"cmds", stage.ExecutorCmds)
|
||||
executor, ok := executorMap[stage.ExecutorName]
|
||||
slog.Info("executor run start", "name", stage.Executor.Name)
|
||||
slog.Debug("executor run start", "name", stage.Executor.Name,
|
||||
"cmds", stage.Executor.Cmds)
|
||||
executor, ok := executorMap[stage.Executor.Name]
|
||||
if !ok {
|
||||
slog.Error("executor not found", "name", stage.ExecutorName)
|
||||
err = fmt.Errorf("executor not found: %s", stage.ExecutorName)
|
||||
slog.Error("executor not found", "name", stage.Executor.Name)
|
||||
err = fmt.Errorf("executor not found: %s", stage.Executor.Name)
|
||||
return
|
||||
}
|
||||
executorResults, err = executor.Run(stage.ExecutorCmds)
|
||||
executorResults, err = executor.Run(stage.Executor.Cmds)
|
||||
if err != nil {
|
||||
slog.Error("executor run error", "name", stage.ExecutorName, "error", err)
|
||||
slog.Error("executor run error", "name", stage.Executor.Name, "error", err)
|
||||
return
|
||||
}
|
||||
slog.Debug("executor run done", "results", executorResults)
|
||||
for _, executorResult := range executorResults {
|
||||
slog.Debug("executor run done", "result.Files", executorResult.Files)
|
||||
}
|
||||
slog.Info("parser run start", "name", stage.ParserName)
|
||||
slog.Debug("parser run start", "name", stage.ParserName,
|
||||
"conf", stage.ParserConf)
|
||||
parser, ok := parserMap[stage.ParserName]
|
||||
if !ok {
|
||||
slog.Error("parser not found", "name", stage.ParserName)
|
||||
err = fmt.Errorf("parser not found: %s", stage.ParserName)
|
||||
return
|
||||
parserResults = []ParserResult{}
|
||||
stageForceQuit := false
|
||||
for _, stageParser := range stage.Parsers {
|
||||
slog.Info("parser run start", "name", stageParser.Name)
|
||||
slog.Debug("parser run start", "name", stageParser.Name,
|
||||
"conf", stageParser.Conf)
|
||||
parser, ok := parserMap[stageParser.Name]
|
||||
if !ok {
|
||||
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{
|
||||
Name: stage.Name,
|
||||
Results: parserResults,
|
||||
ForceQuit: forceQuit,
|
||||
ForceQuit: stageForceQuit,
|
||||
})
|
||||
if forceQuit {
|
||||
slog.Error("parser force quit", "name", stage.ParserName)
|
||||
return
|
||||
if stageForceQuit {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
|
|
Loading…
Reference in New Issue
Block a user