feat: repo health check (#16) #17
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
@ -38,10 +37,7 @@ func setupSlog() {
|
||||||
|
|
||||||
// Generally, err is used for runtime errors, and checkRes is used for the result of the checks.
|
// Generally, err is used for runtime errors, and checkRes is used for the result of the checks.
|
||||||
func main() {
|
func main() {
|
||||||
var info []healthcheck.CheckStage
|
|
||||||
var gitWhitelist, metaFile, releaseTags []string
|
var gitWhitelist, metaFile, releaseTags []string
|
||||||
var tmp healthcheck.CheckStage
|
|
||||||
|
|
||||||
rootDir := flag.String("root", "", "")
|
rootDir := flag.String("root", "", "")
|
||||||
repo := flag.String("repo", "", "")
|
repo := flag.String("repo", "", "")
|
||||||
droneBranch := flag.String("droneBranch", "", "")
|
droneBranch := flag.String("droneBranch", "", "")
|
||||||
|
@ -54,33 +50,35 @@ func main() {
|
||||||
parseMultiValueFlag(&releaseTags, "releaseTags", "")
|
parseMultiValueFlag(&releaseTags, "releaseTags", "")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
setupSlog()
|
setupSlog()
|
||||||
tmp = healthcheck.RepoSize()
|
var err error
|
||||||
info = append(info, tmp)
|
err = healthcheck.RepoSize()
|
||||||
|
|
||||||
tmp = healthcheck.ForbiddenCheck(*rootDir, gitWhitelist, *repo, *droneBranch)
|
|
||||||
info = append(info, tmp)
|
|
||||||
|
|
||||||
tmp = healthcheck.MetaCheck(*rootDir, metaFile)
|
|
||||||
info = append(info, tmp)
|
|
||||||
|
|
||||||
tmp = healthcheck.NonAsciiFiles(*rootDir)
|
|
||||||
info = append(info, tmp)
|
|
||||||
|
|
||||||
tmp = healthcheck.NonAsciiMsg(*rootDir)
|
|
||||||
info = append(info, tmp)
|
|
||||||
|
|
||||||
// TODO: find a way to test the release tag
|
|
||||||
tmp = healthcheck.CheckReleases(*rootDir, *releaseCategories, *releaseNumber)
|
|
||||||
info = append(info, tmp)
|
|
||||||
|
|
||||||
// FIXME: for drone usage
|
|
||||||
tmp = healthcheck.Verify(*rootDir, *adminDir)
|
|
||||||
info = append(info, tmp)
|
|
||||||
|
|
||||||
jsonData, err := json.Marshal(info)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprint(os.Stderr, err)
|
fmt.Printf("## Repo Size Check Failed:\n%s\n", err.Error())
|
||||||
os.Exit(1)
|
}
|
||||||
|
err = healthcheck.ForbiddenCheck(*rootDir, gitWhitelist, *repo, *droneBranch)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("## Forbidden File Check Failed:\n%s\n", err.Error())
|
||||||
|
}
|
||||||
|
err = healthcheck.MetaCheck(*rootDir, metaFile)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("## Forbidden File Check Failed:\n%s\n", err.Error())
|
||||||
|
}
|
||||||
|
err = healthcheck.NonAsciiFiles(*rootDir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("## Non-ASCII Characters File Check Failed:\n%s\n", err.Error())
|
||||||
|
}
|
||||||
|
err = healthcheck.NonAsciiMsg(*rootDir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("## Non-ASCII Characters Commit Message Check Failed:\n%s\n", err.Error())
|
||||||
|
}
|
||||||
|
// TODO: find a way to test the release tag
|
||||||
|
err = healthcheck.CheckReleases(*rootDir, *releaseCategories, *releaseNumber)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("## Release Tag Check Failed:\n%s\n", err.Error())
|
||||||
|
}
|
||||||
|
// FIXME: for drone usage
|
||||||
|
err = healthcheck.VerifyDirectory(*rootDir, *adminDir)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("## Directory File Check Failed:\n%s\n", err.Error())
|
||||||
}
|
}
|
||||||
fmt.Printf("%s", jsonData)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,41 +7,35 @@ import (
|
||||||
"github.com/criyle/go-judge/envexec"
|
"github.com/criyle/go-judge/envexec"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Conf struct {
|
|
||||||
Score int
|
|
||||||
Comment string
|
|
||||||
}
|
|
||||||
|
|
||||||
type Healthcheck struct{}
|
type Healthcheck struct{}
|
||||||
|
|
||||||
func Parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
|
func Parse(executorResult stage.ExecutorResult) (stage.ParserResult, bool) {
|
||||||
stdout := executorResult.Files["stdout"]
|
stdout := executorResult.Files["stdout"]
|
||||||
stderr := executorResult.Files["stderr"]
|
stderr := executorResult.Files["stderr"]
|
||||||
if executorResult.Status != stage.Status(envexec.StatusAccepted) {
|
if executorResult.Status != stage.Status(envexec.StatusAccepted) {
|
||||||
return stage.ParserResult{
|
return stage.ParserResult{
|
||||||
Score: 0,
|
Score: 0,
|
||||||
Comment: fmt.Sprintf(
|
Comment: fmt.Sprintf(
|
||||||
"Unexpected executor status: %s.\nStderr: %s",
|
"Unexpected executor status: %s.\nStdout: %s\nStderr: %s",
|
||||||
executorResult.Status, stderr,
|
executorResult.Status, stdout, stderr,
|
||||||
),
|
),
|
||||||
}
|
}, true
|
||||||
}
|
}
|
||||||
return stage.ParserResult{
|
return stage.ParserResult{
|
||||||
Score: 0,
|
Score: 0,
|
||||||
Comment: stdout,
|
Comment: stdout,
|
||||||
}
|
}, stdout != ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (*Healthcheck) Run(results []stage.ExecutorResult, confAny any) (
|
func (*Healthcheck) Run(results []stage.ExecutorResult, confAny any) (
|
||||||
[]stage.ParserResult, bool, error,
|
[]stage.ParserResult, bool, error,
|
||||||
) {
|
) {
|
||||||
conf, err := stage.DecodeConf[Conf](confAny)
|
|
||||||
if err != nil {
|
|
||||||
return nil, true, err
|
|
||||||
}
|
|
||||||
var res []stage.ParserResult
|
var res []stage.ParserResult
|
||||||
|
forceQuit := false
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
res = append(res, Parse(result, *conf))
|
parserResult, forceQuitResult := Parse(result)
|
||||||
|
res = append(res, parserResult)
|
||||||
|
forceQuit = forceQuit || forceQuitResult
|
||||||
}
|
}
|
||||||
return res, false, nil
|
return res, forceQuit, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package healthcheck
|
package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
"unicode"
|
"unicode"
|
||||||
|
@ -14,36 +15,23 @@ import (
|
||||||
// Otherwise, it iterates over each character in the message and checks if it is a non-ASCII character.
|
// Otherwise, it iterates over each character in the message and checks if it is a non-ASCII character.
|
||||||
// If a non-ASCII character is found, it returns an error indicating not to use non-ASCII characters in commit messages.
|
// If a non-ASCII character is found, it returns an error indicating not to use non-ASCII characters in commit messages.
|
||||||
// Otherwise, it returns nil indicating that the commit message is valid.
|
// Otherwise, it returns nil indicating that the commit message is valid.
|
||||||
func NonAsciiMsg(root string) (jsonOut CheckStage) {
|
func NonAsciiMsg(root string) error {
|
||||||
jsonOut = CheckStage{
|
|
||||||
Name: "NonAsciiMsg",
|
|
||||||
StdOut: "Checking for non-ASCII characters in commit message: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
// cmd := exec.Command("git", "log", "--encoding=UTF-8", "--format=%B")
|
// cmd := exec.Command("git", "log", "--encoding=UTF-8", "--format=%B")
|
||||||
repo, err := git.PlainOpen(root)
|
repo, err := git.PlainOpen(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 1
|
|
||||||
slog.Error("openning git repo", "err", err)
|
slog.Error("openning git repo", "err", err)
|
||||||
return jsonOut
|
return fmt.Errorf("error openning git repo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
ref, err := repo.Head()
|
ref, err := repo.Head()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 1
|
|
||||||
slog.Error("getting reference", "err", err)
|
slog.Error("getting reference", "err", err)
|
||||||
return jsonOut
|
return fmt.Errorf("error getting reference: %v", err)
|
||||||
}
|
}
|
||||||
commits, err := repo.Log(&git.LogOptions{From: ref.Hash()})
|
commits, err := repo.Log(&git.LogOptions{From: ref.Hash()})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 1
|
|
||||||
slog.Error("getting commits", "err", err)
|
slog.Error("getting commits", "err", err)
|
||||||
return jsonOut
|
return fmt.Errorf("error getting commits: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var msgs []string
|
var msgs []string
|
||||||
|
@ -52,10 +40,8 @@ func NonAsciiMsg(root string) (jsonOut CheckStage) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
slog.Error("iterating commits", "err", err)
|
||||||
jsonOut.ExitCode = 1
|
return fmt.Errorf("error iterating commits: %v", err)
|
||||||
slog.Error("converting log to string", "err", err)
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nonAsciiMsgs []string
|
var nonAsciiMsgs []string
|
||||||
|
@ -73,11 +59,7 @@ func NonAsciiMsg(root string) (jsonOut CheckStage) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(nonAsciiMsgs) > 0 {
|
if len(nonAsciiMsgs) > 0 {
|
||||||
jsonOut.StdOut += "Failed"
|
return fmt.Errorf("Non-ASCII characters in commit messages:\n" + strings.Join(nonAsciiMsgs, "\n"))
|
||||||
jsonOut.ExitCode = 105
|
|
||||||
jsonOut.StdErr = "Non-ASCII characters in commit messages:\n" + strings.Join(nonAsciiMsgs, "\n")
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
jsonOut.StdOut += "OK"
|
return nil
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,6 @@ func getForbiddens(root string, fileList []string) ([]string, error) {
|
||||||
var regexList []*regexp.Regexp
|
var regexList []*regexp.Regexp
|
||||||
regexList, err := getRegex(fileList)
|
regexList, err := getRegex(fileList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("Error compiling regex:", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,24 +51,11 @@ func getForbiddens(root string, fileList []string) ([]string, error) {
|
||||||
|
|
||||||
// forbiddenCheck checks for forbidden files in the specified root directory.
|
// forbiddenCheck checks for forbidden files in the specified root directory.
|
||||||
// It prints the list of forbidden files found, along with instructions on how to fix them.
|
// It prints the list of forbidden files found, along with instructions on how to fix them.
|
||||||
func ForbiddenCheck(rootDir string, regexList []string, repo string, droneBranch string) (jsonOut CheckStage) {
|
func ForbiddenCheck(rootDir string, regexList []string, repo string, droneBranch string) error {
|
||||||
jsonOut = CheckStage{
|
|
||||||
Name: "forbiddenFile",
|
|
||||||
StdOut: "Checking forbidden files: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
// INFO: test case
|
|
||||||
// regexList := []string{`\.$`, `\.git`, `\.drone.yml`, `Makefile`, `CMakeLists.txt`,`.*\.go`,`.*\.toml`, `.*\.c`, `.*\.cc`, `.*\.cpp`, `.*\.h`, `.*\.md`}
|
|
||||||
// rootDir = "/Users/zhouzhaojiacheng/Desktop/STUDENT_ORG/TechJI/Dev/joj/JOJ3"
|
|
||||||
|
|
||||||
forbids, err := getForbiddens(rootDir, regexList)
|
forbids, err := getForbiddens(rootDir, regexList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
slog.Error("getting forbiddens", "error", err)
|
||||||
jsonOut.ExitCode = 1
|
return fmt.Errorf("error getting forbiddens: %w", err)
|
||||||
slog.Error("get forbiddens", "error", err)
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var message string
|
var message string
|
||||||
|
@ -84,12 +70,7 @@ func ForbiddenCheck(rootDir string, regexList []string, repo string, droneBranch
|
||||||
message += fmt.Sprint(file, " ")
|
message += fmt.Sprint(file, " ")
|
||||||
}
|
}
|
||||||
message += fmt.Sprint("; do git filter-repo --force --invert-paths --path \\\"\\$i\\\"; done\ngit remote add origin ", repo, "\ngit push --set-upstream origin ", droneBranch, " --force")
|
message += fmt.Sprint("; do git filter-repo --force --invert-paths --path \\\"\\$i\\\"; done\ngit remote add origin ", repo, "\ngit push --set-upstream origin ", droneBranch, " --force")
|
||||||
jsonOut.StdOut += "Failed"
|
return fmt.Errorf(message)
|
||||||
jsonOut.ExitCode = 103
|
|
||||||
jsonOut.StdErr = message
|
|
||||||
return jsonOut
|
|
||||||
} else {
|
|
||||||
jsonOut.StdOut += "OK"
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ func getMetas(rootDir string, fileList []string) ([]string, string, error) {
|
||||||
|
|
||||||
files, err := os.ReadDir(rootDir)
|
files, err := os.ReadDir(rootDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", fmt.Errorf("Error reading directory:%w", err)
|
return nil, "", fmt.Errorf("error reading directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
matched := false
|
matched := false
|
||||||
|
@ -60,28 +60,14 @@ func getMetas(rootDir string, fileList []string) ([]string, string, error) {
|
||||||
|
|
||||||
// metaCheck performs a check for metadata files in the specified root directory.
|
// metaCheck performs a check for metadata files in the specified root directory.
|
||||||
// It prints a message if any required metadata files are missing.
|
// It prints a message if any required metadata files are missing.
|
||||||
func MetaCheck(rootDir string, fileList []string) (jsonOut CheckStage) {
|
func MetaCheck(rootDir string, fileList []string) error {
|
||||||
unmatchedList, umatchedRes, err := getMetas(rootDir, fileList)
|
unmatchedList, umatchedRes, err := getMetas(rootDir, fileList)
|
||||||
jsonOut = CheckStage{
|
|
||||||
Name: "metaFile",
|
|
||||||
StdOut: "Checking the existence of meta file: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.ExitCode = 1
|
slog.Error("getting metas", "err", err)
|
||||||
slog.Error("get metas", "err", err)
|
return fmt.Errorf("error getting metas: %w", err)
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
if len(unmatchedList) != 0 {
|
||||||
if len(unmatchedList) == 0 {
|
return fmt.Errorf("%d important project files missing\n"+umatchedRes, len(unmatchedList))
|
||||||
jsonOut.StdOut += "OK"
|
|
||||||
return jsonOut
|
|
||||||
} else {
|
|
||||||
jsonOut.ExitCode = 104
|
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.StdErr = fmt.Sprintf("%d important project files missing\n"+umatchedRes, len(unmatchedList))
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,31 +61,14 @@ func getNonAscii(root string) ([]string, error) {
|
||||||
|
|
||||||
// nonAsciiFiles checks for non-ASCII characters in files within the specified root directory.
|
// nonAsciiFiles checks for non-ASCII characters in files within the specified root directory.
|
||||||
// It prints a message with the paths to files containing non-ASCII characters, if any.
|
// It prints a message with the paths to files containing non-ASCII characters, if any.
|
||||||
func NonAsciiFiles(root string) (jsonOut CheckStage) {
|
func NonAsciiFiles(root string) error {
|
||||||
jsonOut = CheckStage{
|
|
||||||
Name: "NonAsciiFiles",
|
|
||||||
StdOut: "Checking for non-ascii files: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
nonAscii, err := getNonAscii(root)
|
nonAscii, err := getNonAscii(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
slog.Error("getting non-ascii", "err", err)
|
||||||
jsonOut.ExitCode = 1
|
return fmt.Errorf("error getting non-ascii: %w", err)
|
||||||
slog.Error("get non-ascii", "err", err)
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var nonAsciiRes string
|
|
||||||
if len(nonAscii) > 0 {
|
if len(nonAscii) > 0 {
|
||||||
nonAsciiRes = fmt.Sprintf("Non-ASCII characters found in the following files:\n" + strings.Join(nonAscii, "\n"))
|
return fmt.Errorf("Non-ASCII characters found in the following files:\n" + strings.Join(nonAscii, "\n"))
|
||||||
jsonOut.ExitCode = 105
|
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
} else {
|
|
||||||
jsonOut.StdOut += "OK"
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
jsonOut.StdErr = nonAsciiRes
|
|
||||||
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,6 @@ package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
|
||||||
|
|
||||||
"github.com/go-git/go-git/v5"
|
"github.com/go-git/go-git/v5"
|
||||||
"github.com/go-git/go-git/v5/plumbing"
|
"github.com/go-git/go-git/v5/plumbing"
|
||||||
|
@ -19,12 +18,12 @@ func catTags(all []string) (out string) {
|
||||||
func getTagsFromRepo(repoPath string) ([]string, error) {
|
func getTagsFromRepo(repoPath string) ([]string, error) {
|
||||||
repo, err := git.PlainOpen(repoPath)
|
repo, err := git.PlainOpen(repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Cannot open repo: %v", err)
|
return nil, fmt.Errorf("error opening repo: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
refs, err := repo.Tags()
|
refs, err := repo.Tags()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Cannot get tags: %v", err)
|
return nil, fmt.Errorf("error getting tags: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var tags []string
|
var tags []string
|
||||||
|
@ -33,27 +32,18 @@ func getTagsFromRepo(repoPath string) ([]string, error) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error while iterating tags: %v", err)
|
return nil, fmt.Errorf("error iterating tags: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return tags, nil
|
return tags, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckReleases(repoPath string, category string, n int) (jsonOut CheckStage) {
|
func CheckReleases(repoPath string, category string, n int) error {
|
||||||
jsonOut = CheckStage{
|
|
||||||
Name: "ReleaseCheck",
|
|
||||||
StdOut: "Checking release tag: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
tags, err := getTagsFromRepo(repoPath)
|
tags, err := getTagsFromRepo(repoPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Error in getting tags: %v", err)
|
return fmt.Errorf("error getting tags: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var prefix string
|
var prefix string
|
||||||
|
|
||||||
switch category {
|
switch category {
|
||||||
case "exam":
|
case "exam":
|
||||||
prefix = "e"
|
prefix = "e"
|
||||||
|
@ -64,7 +54,6 @@ func CheckReleases(repoPath string, category string, n int) (jsonOut CheckStage)
|
||||||
default:
|
default:
|
||||||
prefix = "a"
|
prefix = "a"
|
||||||
}
|
}
|
||||||
|
|
||||||
target := prefix + fmt.Sprintf("%d", n)
|
target := prefix + fmt.Sprintf("%d", n)
|
||||||
found := false
|
found := false
|
||||||
for _, tag := range tags {
|
for _, tag := range tags {
|
||||||
|
@ -75,14 +64,7 @@ func CheckReleases(repoPath string, category string, n int) (jsonOut CheckStage)
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
tagList := catTags(tags)
|
tagList := catTags(tags)
|
||||||
jsonOut.ExitCode = 107
|
return fmt.Errorf("Wrong release tag '%s'. Please use one of %s.", target, tagList)
|
||||||
jsonOut.StdOut = "Failed"
|
|
||||||
jsonOut.StdErr = fmt.Sprintf("wrong release tag '%s', please use one of %s aborting", target, tagList)
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
return nil
|
||||||
jsonOut.StdOut += "OK"
|
|
||||||
jsonOut.ExitCode = 0
|
|
||||||
jsonOut.StdErr = "Fine"
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package healthcheck
|
package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -9,25 +10,15 @@ 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() (jsonOut CheckStage) {
|
func RepoSize() error {
|
||||||
jsonOut = CheckStage{
|
|
||||||
Name: "RepoSize",
|
|
||||||
StdOut: "Checking repository size: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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")
|
||||||
output, err := cmd.CombinedOutput()
|
output, err := cmd.CombinedOutput()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 1
|
|
||||||
slog.Error("running git command:", "err", err)
|
slog.Error("running git command:", "err", err)
|
||||||
return jsonOut
|
return fmt.Errorf("error running git command: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
lines := strings.Split(string(output), "\n")
|
lines := strings.Split(string(output), "\n")
|
||||||
var sum int
|
var sum int
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
|
@ -36,21 +27,14 @@ func RepoSize() (jsonOut CheckStage) {
|
||||||
sizeStr := fields[1]
|
sizeStr := fields[1]
|
||||||
size, err := strconv.Atoi(sizeStr)
|
size, err := strconv.Atoi(sizeStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 1
|
|
||||||
slog.Error("running git command:", "err", err)
|
slog.Error("running git command:", "err", err)
|
||||||
return jsonOut
|
return fmt.Errorf("error running git command: %w", err)
|
||||||
}
|
}
|
||||||
sum += size
|
sum += size
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if sum > 2048 {
|
||||||
if sum <= 2048 {
|
return fmt.Errorf("Repository larger than 2MB. Please clean up or contact the teaching team.")
|
||||||
jsonOut.StdOut += "OK"
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
jsonOut.StdOut += "Failed"
|
return nil
|
||||||
jsonOut.ExitCode = 100
|
|
||||||
jsonOut.StdErr = "repository larger than 2MB, please clean up or contact the teaching team."
|
|
||||||
return jsonOut
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,15 +5,6 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
// For ExitCode, see https://focs.ji.sjtu.edu.cn/git/TAs/resources/src/branch/drone/dronelib.checks
|
|
||||||
// 1 for unrecoverable error and 0 for succeses
|
|
||||||
type CheckStage struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
StdOut string `json:"stdout"`
|
|
||||||
ExitCode int `json:"exit code"`
|
|
||||||
StdErr string `json:"stderr"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// addExt appends the specified extension to each file name in the given fileList.
|
// addExt appends the specified extension to each file name in the given fileList.
|
||||||
// It modifies the original fileList in place.
|
// It modifies the original fileList in place.
|
||||||
func addExt(fileList []string, ext string) {
|
func addExt(fileList []string, ext string) {
|
||||||
|
|
|
@ -47,68 +47,27 @@ func filesMatch(file1, file2 string) (bool, error) {
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// compareDirectories compares the contents of two directories.
|
// VerifyDirectory checks if the contents of two directories are identical.
|
||||||
func compareDirectories(dir1, dir2 string, jsonOut *CheckStage) error {
|
func VerifyDirectory(rootDir, compareDir string) error {
|
||||||
allMatch := true
|
err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error {
|
||||||
var message string
|
|
||||||
err := filepath.Walk(dir1, func(path string, info os.FileInfo, err error) error {
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("error walking directory: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !info.IsDir() {
|
if !info.IsDir() {
|
||||||
relPath, _ := filepath.Rel(dir1, path)
|
relPath, _ := filepath.Rel(rootDir, path)
|
||||||
file2 := filepath.Join(dir2, relPath)
|
file2 := filepath.Join(compareDir, relPath)
|
||||||
|
|
||||||
if !fileExists(file2) {
|
if !fileExists(file2) {
|
||||||
// fmt.Printf("File %s in %s is missing in %s\n, please immediately revert your changes!\n", relPath, dir1, dir2)
|
return fmt.Errorf("File %s in %s is missing in %s. Please immediately revert your changes!\n", relPath, rootDir, compareDir)
|
||||||
message += "File missing"
|
|
||||||
allMatch = false
|
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 101
|
|
||||||
jsonOut.StdErr = message
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// fmt.Printf("Checking integrity of %s:\n", path)
|
|
||||||
match, err := filesMatch(path, file2)
|
match, err := filesMatch(path, file2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return fmt.Errorf("error matching files: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !match {
|
if !match {
|
||||||
// fmt.Printf("File %s in %s is not identical to %s\nPlease revert your changes or contact the teaching team if you have a valid reason for adjusting them.\n", relPath, dir1, dir2)
|
return fmt.Errorf("File %s in %s is not identical to %s. Please revert your changes or contact the teaching team if you have a valid reason for adjusting them.\n", relPath, rootDir, compareDir)
|
||||||
message += "File is not identical"
|
|
||||||
allMatch = false
|
|
||||||
jsonOut.StdOut += "Failed"
|
|
||||||
jsonOut.ExitCode = 101
|
|
||||||
jsonOut.StdErr = message
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
if allMatch {
|
|
||||||
jsonOut.StdOut += "OK!"
|
|
||||||
} else {
|
|
||||||
jsonOut.StdOut += "Failed!"
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify checks if the contents of two directories are identical.
|
|
||||||
func Verify(rootDir, compareDir string) CheckStage {
|
|
||||||
jsonOut := CheckStage{
|
|
||||||
Name: "verifyFile",
|
|
||||||
StdOut: "Checking files to be verified: ",
|
|
||||||
ExitCode: 0,
|
|
||||||
StdErr: "",
|
|
||||||
}
|
|
||||||
err := compareDirectories(rootDir, compareDir, &jsonOut)
|
|
||||||
// fmt.Println("Comparison finished ")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("Error:", err)
|
|
||||||
}
|
|
||||||
return jsonOut
|
|
||||||
}
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user