feat(cmd/joj3): extra summary info from teapot [force build]
This commit is contained in:
parent
7b4d167448
commit
e4bfcfbe8d
|
@ -9,6 +9,7 @@ import (
|
||||||
"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
|
"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
|
||||||
"github.com/joint-online-judge/JOJ3/cmd/joj3/stage"
|
"github.com/joint-online-judge/JOJ3/cmd/joj3/stage"
|
||||||
"github.com/joint-online-judge/JOJ3/cmd/joj3/teapot"
|
"github.com/joint-online-judge/JOJ3/cmd/joj3/teapot"
|
||||||
|
internalStage "github.com/joint-online-judge/JOJ3/internal/stage"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -31,7 +32,37 @@ func init() {
|
||||||
showVersion = flag.Bool("version", false, "print current version")
|
showVersion = flag.Bool("version", false, "print current version")
|
||||||
}
|
}
|
||||||
|
|
||||||
func mainImpl() error {
|
func mainImpl() (err error) {
|
||||||
|
confObj := new(conf.Conf)
|
||||||
|
var stageResults []internalStage.StageResult
|
||||||
|
var stageForceQuit bool
|
||||||
|
var teapotResult teapot.TeapotResult
|
||||||
|
defer func() {
|
||||||
|
actor := os.Getenv("GITHUB_ACTOR")
|
||||||
|
repository := os.Getenv("GITHUB_REPOSITORY")
|
||||||
|
ref := os.Getenv("GITHUB_REF")
|
||||||
|
workflow := os.Getenv("GITHUB_WORKFLOW")
|
||||||
|
totalScore := 0
|
||||||
|
for _, stageResult := range stageResults {
|
||||||
|
for _, result := range stageResult.Results {
|
||||||
|
totalScore += result.Score
|
||||||
|
}
|
||||||
|
}
|
||||||
|
slog.Info(
|
||||||
|
"joj3 summary",
|
||||||
|
"name", confObj.Name,
|
||||||
|
"totalScore", totalScore,
|
||||||
|
"forceQuit", stageForceQuit,
|
||||||
|
"actor", actor,
|
||||||
|
"repository", repository,
|
||||||
|
"ref", ref,
|
||||||
|
"workflow", workflow,
|
||||||
|
"issue", teapotResult.Issue,
|
||||||
|
"action", teapotResult.Action,
|
||||||
|
"sha", teapotResult.Sha,
|
||||||
|
"error", err,
|
||||||
|
)
|
||||||
|
}()
|
||||||
if err := setupSlog(""); err != nil { // before conf is loaded
|
if err := setupSlog(""); err != nil { // before conf is loaded
|
||||||
slog.Error("setup slog", "error", err)
|
slog.Error("setup slog", "error", err)
|
||||||
return err
|
return err
|
||||||
|
@ -57,7 +88,7 @@ func mainImpl() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
slog.Info("try to load conf", "path", confPath)
|
slog.Info("try to load conf", "path", confPath)
|
||||||
confObj, err := conf.ParseConfFile(confPath)
|
confObj, err = conf.ParseConfFile(confPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("parse conf", "error", err)
|
slog.Error("parse conf", "error", err)
|
||||||
return err
|
return err
|
||||||
|
@ -79,16 +110,16 @@ func mainImpl() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
groups := conf.MatchGroups(confObj, conventionalCommit)
|
groups := conf.MatchGroups(confObj, conventionalCommit)
|
||||||
stageResults, stageForceQuit, err := stage.Run(confObj, groups)
|
stageResults, stageForceQuit, err = stage.Run(confObj, groups)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("stage run", "error", err)
|
slog.Error("stage run", "error", err)
|
||||||
}
|
}
|
||||||
stage.Summarize(confObj, stageResults, stageForceQuit)
|
|
||||||
if err = stage.Write(confObj.Stage.OutputPath, stageResults); err != nil {
|
if err = stage.Write(confObj.Stage.OutputPath, stageResults); err != nil {
|
||||||
slog.Error("stage write", "error", err)
|
slog.Error("stage write", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := teapot.Run(confObj, runID); err != nil {
|
teapotResult, err = teapot.Run(confObj, runID)
|
||||||
|
if err != nil {
|
||||||
slog.Error("teapot run", "error", err)
|
slog.Error("teapot run", "error", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,6 +13,8 @@ import (
|
||||||
"github.com/jinzhu/copier"
|
"github.com/jinzhu/copier"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type StageResult stage.StageResult
|
||||||
|
|
||||||
func generateStages(conf *conf.Conf, groups []string) ([]stage.Stage, error) {
|
func generateStages(conf *conf.Conf, groups []string) ([]stage.Stage, error) {
|
||||||
stages := []stage.Stage{}
|
stages := []stage.Stage{}
|
||||||
existNames := map[string]bool{}
|
existNames := map[string]bool{}
|
||||||
|
|
|
@ -1,34 +0,0 @@
|
||||||
package stage
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log/slog"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
|
|
||||||
"github.com/joint-online-judge/JOJ3/internal/stage"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Summarize(
|
|
||||||
conf *conf.Conf, stageResults []stage.StageResult, stageForceQuit bool,
|
|
||||||
) {
|
|
||||||
actor := os.Getenv("GITHUB_ACTOR")
|
|
||||||
repository := os.Getenv("GITHUB_REPOSITORY")
|
|
||||||
ref := os.Getenv("GITHUB_REF")
|
|
||||||
workflow := os.Getenv("GITHUB_WORKFLOW")
|
|
||||||
totalScore := 0
|
|
||||||
for _, stageResult := range stageResults {
|
|
||||||
for _, result := range stageResult.Results {
|
|
||||||
totalScore += result.Score
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slog.Info(
|
|
||||||
"stage summary",
|
|
||||||
"name", conf.Name,
|
|
||||||
"totalScore", totalScore,
|
|
||||||
"forceQuit", stageForceQuit,
|
|
||||||
"actor", actor,
|
|
||||||
"repository", repository,
|
|
||||||
"ref", ref,
|
|
||||||
"workflow", workflow,
|
|
||||||
)
|
|
||||||
}
|
|
|
@ -2,6 +2,8 @@ package teapot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
|
@ -14,7 +16,13 @@ import (
|
||||||
"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
|
"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Run(conf *conf.Conf, runID string) error {
|
type TeapotResult struct {
|
||||||
|
Issue int `json:"issue"`
|
||||||
|
Action int `json:"action"`
|
||||||
|
Sha string `json:"sha"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func Run(conf *conf.Conf, runID string) (teapotResult TeapotResult, err error) {
|
||||||
os.Setenv("LOG_FILE_PATH", conf.Teapot.LogPath)
|
os.Setenv("LOG_FILE_PATH", conf.Teapot.LogPath)
|
||||||
os.Setenv("_TYPER_STANDARD_TRACEBACK", "1")
|
os.Setenv("_TYPER_STANDARD_TRACEBACK", "1")
|
||||||
sha := os.Getenv("GITHUB_SHA")
|
sha := os.Getenv("GITHUB_SHA")
|
||||||
|
@ -24,52 +32,11 @@ func Run(conf *conf.Conf, runID string) error {
|
||||||
if actor == "" || repository == "" || strings.Count(repository, "/") != 1 ||
|
if actor == "" || repository == "" || strings.Count(repository, "/") != 1 ||
|
||||||
runNumber == "" {
|
runNumber == "" {
|
||||||
slog.Error("teapot env not set")
|
slog.Error("teapot env not set")
|
||||||
return fmt.Errorf("teapot env not set")
|
err = fmt.Errorf("teapot env not set")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
repoParts := strings.Split(repository, "/")
|
repoParts := strings.Split(repository, "/")
|
||||||
repoName := repoParts[1]
|
repoName := repoParts[1]
|
||||||
re := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
|
|
||||||
execCommand := func(name string, cmdArgs []string) error {
|
|
||||||
cmd := exec.Command(name, cmdArgs...) // #nosec G204
|
|
||||||
stderr, err := cmd.StderrPipe()
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("stderr pipe", "error", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
var wg sync.WaitGroup
|
|
||||||
wg.Add(1)
|
|
||||||
scanner := bufio.NewScanner(stderr)
|
|
||||||
go func() {
|
|
||||||
for scanner.Scan() {
|
|
||||||
text := re.ReplaceAllString(scanner.Text(), "")
|
|
||||||
if text == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
slog.Info(name, "stderr", text)
|
|
||||||
}
|
|
||||||
wg.Done()
|
|
||||||
if scanner.Err() != nil {
|
|
||||||
slog.Error("stderr scanner", "error", scanner.Err())
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if err = cmd.Start(); err != nil {
|
|
||||||
slog.Error("cmd start", "error", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
wg.Wait()
|
|
||||||
if err = cmd.Wait(); err != nil {
|
|
||||||
if exitErr, ok := err.(*exec.ExitError); ok {
|
|
||||||
exitCode := exitErr.ExitCode()
|
|
||||||
slog.Error("cmd completed with non-zero exit code",
|
|
||||||
"error", err,
|
|
||||||
"exitCode", exitCode)
|
|
||||||
} else {
|
|
||||||
slog.Error("cmd wait", "error", err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
skipIssueArg := "--no-skip-result-issue"
|
skipIssueArg := "--no-skip-result-issue"
|
||||||
if conf.Teapot.SkipIssue {
|
if conf.Teapot.SkipIssue {
|
||||||
skipIssueArg = "--skip-result-issue"
|
skipIssueArg = "--skip-result-issue"
|
||||||
|
@ -86,7 +53,8 @@ func Run(conf *conf.Conf, runID string) error {
|
||||||
if conf.Teapot.SubmitterInIssueTitle {
|
if conf.Teapot.SubmitterInIssueTitle {
|
||||||
submitterInIssueTitleArg = "--submitter-in-issue-title"
|
submitterInIssueTitleArg = "--submitter-in-issue-title"
|
||||||
}
|
}
|
||||||
if err := execCommand("joint-teapot", []string{
|
re := regexp.MustCompile(`\x1b\[[0-9;]*[a-zA-Z]`)
|
||||||
|
cmd := exec.Command("joint-teapot",
|
||||||
"joj3-all", conf.Teapot.EnvFilePath, conf.Stage.OutputPath, actor,
|
"joj3-all", conf.Teapot.EnvFilePath, conf.Stage.OutputPath, actor,
|
||||||
conf.Teapot.GradingRepoName, repoName, runNumber,
|
conf.Teapot.GradingRepoName, repoName, runNumber,
|
||||||
conf.Teapot.ScoreboardPath, conf.Teapot.FailedTablePath,
|
conf.Teapot.ScoreboardPath, conf.Teapot.FailedTablePath,
|
||||||
|
@ -94,9 +62,51 @@ func Run(conf *conf.Conf, runID string) error {
|
||||||
"--max-total-score", strconv.Itoa(conf.Teapot.MaxTotalScore),
|
"--max-total-score", strconv.Itoa(conf.Teapot.MaxTotalScore),
|
||||||
skipIssueArg, skipScoreboardArg,
|
skipIssueArg, skipScoreboardArg,
|
||||||
skipFailedTableArg, submitterInIssueTitleArg,
|
skipFailedTableArg, submitterInIssueTitleArg,
|
||||||
}); err != nil {
|
) // #nosec G204
|
||||||
slog.Error("teapot exit", "error", err)
|
stdoutBuf := new(bytes.Buffer)
|
||||||
return fmt.Errorf("teapot exit")
|
cmd.Stdout = stdoutBuf
|
||||||
|
stderr, err := cmd.StderrPipe()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("stderr pipe", "error", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
return nil
|
var wg sync.WaitGroup
|
||||||
|
wg.Add(1)
|
||||||
|
scanner := bufio.NewScanner(stderr)
|
||||||
|
go func() {
|
||||||
|
for scanner.Scan() {
|
||||||
|
text := re.ReplaceAllString(scanner.Text(), "")
|
||||||
|
if text == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
slog.Info("joint-teapot", "stderr", text)
|
||||||
|
}
|
||||||
|
wg.Done()
|
||||||
|
if scanner.Err() != nil {
|
||||||
|
slog.Error("stderr scanner", "error", scanner.Err())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
if err = cmd.Start(); err != nil {
|
||||||
|
slog.Error("cmd start", "error", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
wg.Wait()
|
||||||
|
if err = cmd.Wait(); err != nil {
|
||||||
|
if exitErr, ok := err.(*exec.ExitError); ok {
|
||||||
|
exitCode := exitErr.ExitCode()
|
||||||
|
slog.Error("cmd completed with non-zero exit code",
|
||||||
|
"error", err,
|
||||||
|
"exitCode", exitCode)
|
||||||
|
} else {
|
||||||
|
slog.Error("cmd wait", "error", err)
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if json.Unmarshal(stdoutBuf.Bytes(), &teapotResult) != nil {
|
||||||
|
slog.Error("unmarshal teapot result", "error", err,
|
||||||
|
"stdout", stdoutBuf.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.Info("teapot result", "result", teapotResult)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user