feat: run stages and teapot in joj3 #47
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package stage
 | 
					package conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,7 @@ import (
 | 
				
			||||||
	"regexp"
 | 
						"regexp"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/go-git/go-git/v5"
 | 
				
			||||||
	"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
						"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
				
			||||||
	"github.com/koding/multiconfig"
 | 
						"github.com/koding/multiconfig"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
| 
						 | 
					@ -73,6 +74,23 @@ type ConventionalCommit struct {
 | 
				
			||||||
	Footer      string
 | 
						Footer      string
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func GetCommitMsg() (msg string, 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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						msg = commit.Message
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseConventionalCommit(commit string) (*ConventionalCommit, error) {
 | 
					func parseConventionalCommit(commit string) (*ConventionalCommit, error) {
 | 
				
			||||||
	re := regexp.MustCompile(`(?s)^(\w+)(\(([^)]+)\))?!?: (.+?)(\n\n(.+?))?(\n\n(.+))?$`)
 | 
						re := regexp.MustCompile(`(?s)^(\w+)(\(([^)]+)\))?!?: (.+?)(\n\n(.+?))?(\n\n(.+))?$`)
 | 
				
			||||||
	matches := re.FindStringSubmatch(strings.TrimSpace(commit))
 | 
						matches := re.FindStringSubmatch(strings.TrimSpace(commit))
 | 
				
			||||||
| 
						 | 
					@ -107,7 +125,7 @@ func parseConfFile(path string) (conf Conf, err error) {
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseMsg(confRoot, confName, msg string) (conf Conf, 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 {
 | 
				
			||||||
| 
						 | 
					@ -142,7 +160,7 @@ func parseMsg(confRoot, confName, msg string) (conf Conf, group string, err erro
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func listValidScopes(confRoot, confName, msg string) ([]string, error) {
 | 
					func ListValidScopes(confRoot, confName, msg string) ([]string, error) {
 | 
				
			||||||
	conventionalCommit, err := parseConventionalCommit(msg)
 | 
						conventionalCommit, err := parseConventionalCommit(msg)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return []string{}, err
 | 
							return []string{}, err
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package stage
 | 
					package conf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"reflect"
 | 
						"reflect"
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package stage
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
| 
						 | 
					@ -1,19 +1,71 @@
 | 
				
			||||||
package main
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"flag"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
	"log/slog"
 | 
						"log/slog"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"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"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var (
 | 
				
			||||||
 | 
						confRoot    string
 | 
				
			||||||
 | 
						confName    string
 | 
				
			||||||
 | 
						msg         string
 | 
				
			||||||
 | 
						showVersion *bool
 | 
				
			||||||
 | 
						Version     string = "debug"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func init() {
 | 
				
			||||||
 | 
						flag.StringVar(&confRoot, "conf-root", ".", "root path for all config files")
 | 
				
			||||||
 | 
						flag.StringVar(&confName, "conf-name", "conf.json", "filename for config files")
 | 
				
			||||||
 | 
						flag.StringVar(&msg, "msg", "", "message to trigger the running, leave empty to use git commit message on HEAD")
 | 
				
			||||||
 | 
						showVersion = flag.Bool("version", false, "print current version")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	// TODO: call stage-runner
 | 
						if err := setupSlog(""); err != nil { // before conf is loaded
 | 
				
			||||||
	if err := stage.Run(); err != nil {
 | 
							slog.Error("setup slog", "error", err)
 | 
				
			||||||
		slog.Error("stage runner error", "error", err)
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	// TODO: call joint-teapot
 | 
						flag.Parse()
 | 
				
			||||||
	if err := teapot.Run(); err != nil {
 | 
						if *showVersion {
 | 
				
			||||||
		slog.Error("teapot caller error", "error", err)
 | 
							fmt.Println(Version)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						slog.Info("start joj3", "version", Version)
 | 
				
			||||||
 | 
						if msg == "" {
 | 
				
			||||||
 | 
							var err error
 | 
				
			||||||
 | 
							msg, err = conf.GetCommitMsg()
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								slog.Error("get commit msg", "error", err)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						confObj, group, err := conf.ParseMsg(confRoot, confName, msg)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							slog.Error("parse msg", "error", err)
 | 
				
			||||||
 | 
							validScopes, scopeErr := conf.ListValidScopes(
 | 
				
			||||||
 | 
								confRoot, confName, msg)
 | 
				
			||||||
 | 
							if scopeErr != nil {
 | 
				
			||||||
 | 
								slog.Error("list valid scopes", "error", scopeErr)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							slog.Info("hint: valid scopes in commit message", "scopes", validScopes)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := setupSlog(confObj.LogPath); err != nil { // after conf is loaded
 | 
				
			||||||
 | 
							slog.Error("setup slog", "error", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := stage.Run(confObj, group); err != nil {
 | 
				
			||||||
 | 
							slog.Error("stage run", "error", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if err := teapot.Run(confObj); err != nil {
 | 
				
			||||||
 | 
							slog.Error("teapot run", "error", err)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,4 +1,4 @@
 | 
				
			||||||
package stage
 | 
					package main
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
| 
						 | 
					@ -63,7 +63,7 @@ func readStageResults(t *testing.T, path string) []stage.StageResult {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestRun(t *testing.T) {
 | 
					func TestRun(t *testing.T) {
 | 
				
			||||||
	var tests []string
 | 
						var tests []string
 | 
				
			||||||
	root := "../../../tmp/submodules/JOJ3-examples/examples/"
 | 
						root := "../../tmp/submodules/JOJ3-examples/examples/"
 | 
				
			||||||
	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
 | 
						err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
| 
						 | 
					@ -105,9 +105,7 @@ func TestRun(t *testing.T) {
 | 
				
			||||||
			os.Args = []string{"./joj3"}
 | 
								os.Args = []string{"./joj3"}
 | 
				
			||||||
			outputFile := "joj3_result.json"
 | 
								outputFile := "joj3_result.json"
 | 
				
			||||||
			defer os.Remove(outputFile)
 | 
								defer os.Remove(outputFile)
 | 
				
			||||||
			if err := Run(); err != nil {
 | 
								main()
 | 
				
			||||||
				t.Fatal(err)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			stageResults := readStageResults(t, outputFile)
 | 
								stageResults := readStageResults(t, outputFile)
 | 
				
			||||||
			regex := true
 | 
								regex := true
 | 
				
			||||||
			expectedFile := "expected_regex.json"
 | 
								expectedFile := "expected_regex.json"
 | 
				
			||||||
| 
						 | 
					@ -2,37 +2,18 @@ package stage
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"flag"
 | 
					 | 
				
			||||||
	"fmt"
 | 
					 | 
				
			||||||
	"log/slog"
 | 
						"log/slog"
 | 
				
			||||||
	"os"
 | 
						"os"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
 | 
				
			||||||
	"github.com/joint-online-judge/JOJ3/internal/executors"
 | 
						"github.com/joint-online-judge/JOJ3/internal/executors"
 | 
				
			||||||
	_ "github.com/joint-online-judge/JOJ3/internal/parsers"
 | 
						_ "github.com/joint-online-judge/JOJ3/internal/parsers"
 | 
				
			||||||
	"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
						"github.com/joint-online-judge/JOJ3/internal/stage"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/go-git/go-git/v5"
 | 
					 | 
				
			||||||
	"github.com/jinzhu/copier"
 | 
						"github.com/jinzhu/copier"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func getCommitMsg() (msg string, err error) {
 | 
					func generateStages(conf conf.Conf, group string) ([]stage.Stage, 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
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	msg = commit.Message
 | 
					 | 
				
			||||||
	return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func generateStages(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.Stages {
 | 
						for _, s := range conf.Stages {
 | 
				
			||||||
| 
						 | 
					@ -92,54 +73,7 @@ func outputResult(outputPath string, results []stage.StageResult) error {
 | 
				
			||||||
		append(content, []byte("\n")...), 0o600)
 | 
							append(content, []byte("\n")...), 0o600)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					func Run(conf conf.Conf, group string) error {
 | 
				
			||||||
	confRoot    string
 | 
					 | 
				
			||||||
	confName    string
 | 
					 | 
				
			||||||
	msg         string
 | 
					 | 
				
			||||||
	showVersion *bool
 | 
					 | 
				
			||||||
	Version     string = "debug"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func init() {
 | 
					 | 
				
			||||||
	flag.StringVar(&confRoot, "conf-root", ".", "root path for all config files")
 | 
					 | 
				
			||||||
	flag.StringVar(&confName, "conf-name", "conf.json", "filename for config files")
 | 
					 | 
				
			||||||
	flag.StringVar(&msg, "msg", "", "message to trigger the running, leave empty to use git commit message on HEAD")
 | 
					 | 
				
			||||||
	showVersion = flag.Bool("version", false, "print current version")
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func Run() error {
 | 
					 | 
				
			||||||
	if err := setupSlog(""); err != nil { // before conf is loaded
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	flag.Parse()
 | 
					 | 
				
			||||||
	if *showVersion {
 | 
					 | 
				
			||||||
		fmt.Println(Version)
 | 
					 | 
				
			||||||
		return nil
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	slog.Info("start joj3", "version", Version)
 | 
					 | 
				
			||||||
	if msg == "" {
 | 
					 | 
				
			||||||
		var err error
 | 
					 | 
				
			||||||
		msg, err = getCommitMsg()
 | 
					 | 
				
			||||||
		if err != nil {
 | 
					 | 
				
			||||||
			slog.Error("get commit msg", "error", err)
 | 
					 | 
				
			||||||
			return err
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	conf, group, err := parseMsg(confRoot, confName, msg)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		slog.Error("parse msg", "error", err)
 | 
					 | 
				
			||||||
		validScopes, scopeErr := listValidScopes(
 | 
					 | 
				
			||||||
			confRoot, confName, msg)
 | 
					 | 
				
			||||||
		if scopeErr != nil {
 | 
					 | 
				
			||||||
			slog.Error("list valid scopes", "error", scopeErr)
 | 
					 | 
				
			||||||
			return scopeErr
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		slog.Info("hint: valid scopes in commit message", "scopes", validScopes)
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if err := setupSlog(conf.LogPath); err != nil { // after conf is loaded
 | 
					 | 
				
			||||||
		return err
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	executors.InitWithConf(conf.SandboxExecServer, conf.SandboxToken)
 | 
						executors.InitWithConf(conf.SandboxExecServer, conf.SandboxToken)
 | 
				
			||||||
	stages, err := generateStages(conf, group)
 | 
						stages, err := generateStages(conf, group)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,9 +3,11 @@ package teapot
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"log/slog"
 | 
						"log/slog"
 | 
				
			||||||
	"os/exec"
 | 
						"os/exec"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/joint-online-judge/JOJ3/cmd/joj3/conf"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func Run() error {
 | 
					func Run(conf conf.Conf) error {
 | 
				
			||||||
	// TODO: call teapot
 | 
						// TODO: call teapot
 | 
				
			||||||
	cmd := exec.Command("joint-teapot", "--help")
 | 
						cmd := exec.Command("joint-teapot", "--help")
 | 
				
			||||||
	output, err := cmd.CombinedOutput()
 | 
						output, err := cmd.CombinedOutput()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user