fix aggregate
Some checks failed
judge / Build judge (push) Successful in 10s
judge / Linux / gcc / Debug (push) Successful in 9s
judge / Linux / clang / Release (push) Successful in 12s
judge / Linux / clang / Sanitized (push) Successful in 11s
judge / Linux / gcc / Release (push) Successful in 11s
judge / Linux / gcc / Sanitized (push) Successful in 10s
judge / Linux / gcc / Debug (valgrind) (push) Successful in 17s
judge / Windows / clang / Debug (push) Successful in 1m28s
judge / Windows / clang / Release (push) Successful in 1m24s
judge / Windows / msvc / Release (push) Successful in 1m28s
judge / Windows / msvc / Debug (push) Successful in 1m33s
judge / SUMMARY (push) Failing after 4s
Some checks failed
judge / Build judge (push) Successful in 10s
judge / Linux / gcc / Debug (push) Successful in 9s
judge / Linux / clang / Release (push) Successful in 12s
judge / Linux / clang / Sanitized (push) Successful in 11s
judge / Linux / gcc / Release (push) Successful in 11s
judge / Linux / gcc / Sanitized (push) Successful in 10s
judge / Linux / gcc / Debug (valgrind) (push) Successful in 17s
judge / Windows / clang / Debug (push) Successful in 1m28s
judge / Windows / clang / Release (push) Successful in 1m24s
judge / Windows / msvc / Release (push) Successful in 1m28s
judge / Windows / msvc / Debug (push) Successful in 1m33s
judge / SUMMARY (push) Failing after 4s
This commit is contained in:
@@ -156,13 +156,27 @@ jobs:
|
||||
compression-level: 9
|
||||
|
||||
summary:
|
||||
needs: [test]
|
||||
needs: [build_judge, test]
|
||||
if: ${{ always() }}
|
||||
name: SUMMARY
|
||||
runs-on: Linux-Runner
|
||||
timeout-minutes: 5
|
||||
|
||||
steps:
|
||||
- name: Download judge binary
|
||||
uses: https://github.com/christopherHX/gitea-download-artifact@v4
|
||||
with:
|
||||
name: judge-bin
|
||||
path: judge-bin
|
||||
|
||||
- name: Install judge on PATH
|
||||
shell: bash
|
||||
run: |
|
||||
mkdir -p bin
|
||||
cp judge-bin/judge-linux-amd64 bin/judge
|
||||
chmod +x bin/judge
|
||||
echo "$PWD/bin" >> "$GITHUB_PATH"
|
||||
|
||||
- name: Download all reports
|
||||
uses: https://github.com/christopherHX/gitea-download-artifact@v4
|
||||
with:
|
||||
@@ -171,18 +185,7 @@ jobs:
|
||||
|
||||
- name: Aggregate
|
||||
shell: bash
|
||||
run: |
|
||||
echo "# Judge results" > SUMMARY.md
|
||||
echo "" >> SUMMARY.md
|
||||
echo "| Configuration | Score |" >> SUMMARY.md
|
||||
echo "|---|---|" >> SUMMARY.md
|
||||
shopt -s nullglob
|
||||
for f in reports/*/*.json; do
|
||||
cfg=$(basename "$(dirname "$f")" | sed 's/^report_//')
|
||||
score=$(grep -o '"total_score":[^,}]*' "$f" | head -1 | cut -d: -f2)
|
||||
echo "| $cfg | ${score:- -} |" >> SUMMARY.md
|
||||
done
|
||||
cat SUMMARY.md
|
||||
run: judge aggregate reports > SUMMARY.md
|
||||
|
||||
- name: Upload summary
|
||||
uses: https://github.com/christopherHX/gitea-upload-artifact@v4
|
||||
|
||||
@@ -14,6 +14,7 @@ const usage = `judge — CI/CD testing system for student solutions
|
||||
|
||||
Usage:
|
||||
judge <tests.jdg> <solution-dir> [flags]
|
||||
judge aggregate <reports-dir>
|
||||
|
||||
Flags:
|
||||
--json output as JSON instead of text
|
||||
@@ -24,10 +25,15 @@ Flags:
|
||||
Example:
|
||||
judge lab1.jdg ./student-solution
|
||||
judge lab1.jdg ./student-solution --json
|
||||
judge lab1.jdg ./student-solution --wrapper "valgrind --error-exitcode=99"
|
||||
judge aggregate reports/
|
||||
`
|
||||
|
||||
func main() {
|
||||
if len(os.Args) >= 2 && os.Args[1] == "aggregate" {
|
||||
runAggregate()
|
||||
return
|
||||
}
|
||||
|
||||
fs := flag.NewFlagSet("judge", flag.ContinueOnError)
|
||||
fs.SetOutput(os.Stderr)
|
||||
fs.Usage = func() { fmt.Fprint(os.Stderr, usage) }
|
||||
@@ -85,6 +91,16 @@ func main() {
|
||||
}
|
||||
}
|
||||
|
||||
func runAggregate() {
|
||||
if len(os.Args) < 3 {
|
||||
fatalf("usage: judge aggregate <reports-dir>")
|
||||
}
|
||||
dir := os.Args[2]
|
||||
if err := reporter.Aggregate(os.Stdout, dir); err != nil {
|
||||
fatalf("%v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func fatalf(msg string, args ...any) {
|
||||
fmt.Fprintf(os.Stderr, "error: "+msg+"\n", args...)
|
||||
os.Exit(1)
|
||||
|
||||
@@ -4,6 +4,9 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/Mond1c/judge/runner"
|
||||
@@ -74,6 +77,60 @@ type jsonTestResult struct {
|
||||
Failures []string `json:"failures,omitempty"`
|
||||
}
|
||||
|
||||
func Aggregate(w io.Writer, dir string) error {
|
||||
files, err := filepath.Glob(filepath.Join(dir, "*", "*.json"))
|
||||
if err != nil {
|
||||
return fmt.Errorf("glob reports: %w", err)
|
||||
}
|
||||
if len(files) == 0 {
|
||||
files, _ = filepath.Glob(filepath.Join(dir, "*.json"))
|
||||
}
|
||||
if len(files) == 0 {
|
||||
return fmt.Errorf("no JSON reports found in %s", dir)
|
||||
}
|
||||
sort.Strings(files)
|
||||
|
||||
type entry struct {
|
||||
Config string
|
||||
Score float64
|
||||
}
|
||||
|
||||
var entries []entry
|
||||
allPassed := true
|
||||
|
||||
for _, f := range files {
|
||||
data, err := os.ReadFile(f)
|
||||
if err != nil {
|
||||
return fmt.Errorf("read %s: %w", f, err)
|
||||
}
|
||||
var report jsonSuiteResult
|
||||
if err := json.Unmarshal(data, &report); err != nil {
|
||||
return fmt.Errorf("parse %s: %w", f, err)
|
||||
}
|
||||
|
||||
cfg := filepath.Base(filepath.Dir(f))
|
||||
cfg = strings.TrimPrefix(cfg, "report_")
|
||||
|
||||
entries = append(entries, entry{Config: cfg, Score: report.TotalScore})
|
||||
if report.TotalScore < 0.9999 {
|
||||
allPassed = false
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Fprintln(w, "# Judge results")
|
||||
fmt.Fprintln(w)
|
||||
fmt.Fprintln(w, "| Configuration | Score |")
|
||||
fmt.Fprintln(w, "|---|---|")
|
||||
for _, e := range entries {
|
||||
fmt.Fprintf(w, "| %s | %.4f |\n", e.Config, e.Score)
|
||||
}
|
||||
|
||||
if !allPassed {
|
||||
return fmt.Errorf("one or more configurations scored below 1.0")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func jsonResult(r *runner.SuiteResult) jsonSuiteResult {
|
||||
res := jsonSuiteResult{
|
||||
TotalScore: r.TotalScore,
|
||||
|
||||
Reference in New Issue
Block a user