1
0
forked from JOJ/JOJ3

Compare commits

...

10 Commits

Author SHA1 Message Date
be12f79a4e
chore(deps): bump google.golang.org/grpc from v1.79.1 to v1.79.3
Some checks failed
submodules sync / sync (push) Successful in 3m39s
build / build (push) Failing after 10m1s
build / trigger-build-image (push) Has been skipped
2026-03-18 22:18:52 -07:00
bd15d5ce05
fix: groups recording for [all]
Some checks failed
submodules sync / sync (push) Successful in 4m20s
build / build (push) Failing after 12m42s
build / trigger-build-image (push) Has been skipped
2026-03-18 10:50:39 -07:00
e20ebfaa81 fix: check conf file ownership (#98)
All checks were successful
submodules sync / sync (push) Successful in 2m48s
build / build (push) Successful in 8m6s
build / trigger-build-image (push) Successful in 22s
Co-authored-by: arthurcai <arthurcai@sjtu.edu.cn>
Reviewed-on: JOJ/JOJ3#98
Co-authored-by: Boming Zhang <bomingzh@sjtu.edu.cn>
Co-committed-by: Boming Zhang <bomingzh@sjtu.edu.cn>
2026-03-13 17:13:39 +08:00
0a5b3bdc71
chore(deps): bump google.golang.org/grpc from v1.77.0 to v1.79.1
All checks were successful
submodules sync / sync (push) Successful in 1m28s
build / build (push) Successful in 2m52s
build / trigger-build-image (push) Successful in 14s
2026-02-13 01:35:36 -08:00
032a99ff39
chore(deps): bump github.com/go-git/go-git/v5 from v5.16.2 to v5.16.5 2026-02-13 01:33:36 -08:00
a085c7ecba
chore(deps): bump github.com/criyle/go-judge/pb from v1.0.1 to v1.3.2
All checks were successful
submodules sync / sync (push) Successful in 47s
build / build (push) Successful in 2m22s
build / trigger-build-image (push) Successful in 12s
2026-01-07 05:24:01 -08:00
ad3c29a4df
chore(deps): bump github.com/criyle/go-judge/pb from v1.0.0 to v1.0.1
All checks were successful
submodules sync / sync (push) Successful in 1m33s
build / build (push) Successful in 2m55s
build / trigger-build-image (push) Successful in 15s
2026-01-06 23:30:47 -08:00
91a452e23d
feat(parser/log): log string line by line
All checks were successful
submodules sync / sync (push) Successful in 48s
build / build (push) Successful in 3m0s
build / trigger-build-image (push) Successful in 14s
2025-11-27 22:47:52 -08:00
e800bc5c2a
fix(parser/log): handle non json input
All checks were successful
submodules sync / sync (push) Successful in 50s
build / build (push) Successful in 2m54s
build / trigger-build-image (push) Successful in 18s
2025-11-27 22:09:49 -08:00
8155de0c92
chore(deps): bump golang.org/x/crypto from 0.43.0 to 0.45.0
All checks were successful
submodules sync / sync (push) Successful in 1m16s
build / build (push) Successful in 4m42s
build / trigger-build-image (push) Successful in 13s
2025-11-27 20:12:06 -08:00
6 changed files with 176 additions and 123 deletions

View File

@ -13,6 +13,7 @@ import (
"path/filepath" "path/filepath"
"regexp" "regexp"
"strings" "strings"
"syscall"
"github.com/go-git/go-git/v5" "github.com/go-git/go-git/v5"
"github.com/koding/multiconfig" "github.com/koding/multiconfig"
@ -183,6 +184,17 @@ func GetConfPath(confRoot, confName, fallbackConfName, msg, tag string) (
return confPath, confStat, conventionalCommit, err return confPath, confStat, conventionalCommit, err
} }
} }
// Check file ownership
if stat, ok := confStat.Sys().(*syscall.Stat_t); ok {
uid := int(stat.Uid)
currentUID := os.Getuid()
if uid != currentUID {
err = fmt.Errorf("insecure configuration file: owned by uid %d, expected %d", uid, currentUID)
slog.Error("insecure conf file", "path", confPath, "uid", uid, "currentUID", currentUID)
return confPath, confStat, conventionalCommit, err
}
}
return confPath, confStat, conventionalCommit, err return confPath, confStat, conventionalCommit, err
} }
@ -190,20 +202,7 @@ func MatchGroups(conf *Conf, conventionalCommit *ConventionalCommit) []string {
seen := make(map[string]bool) seen := make(map[string]bool)
keywords := []string{} keywords := []string{}
loweredCommitGroup := strings.ToLower(conventionalCommit.Group) loweredCommitGroup := strings.ToLower(conventionalCommit.Group)
if loweredCommitGroup == "all" { matchAllGroups := loweredCommitGroup == "all"
for i := range conf.PreStages {
conf.PreStages[i].Group = ""
conf.PreStages[i].Groups = nil
}
for i := range conf.Stages {
conf.Stages[i].Group = ""
conf.Stages[i].Groups = nil
}
for i := range conf.PostStages {
conf.PostStages[i].Group = ""
conf.PostStages[i].Groups = nil
}
}
confStages := []ConfStage{} confStages := []ConfStage{}
confStages = append(confStages, conf.PreStages...) confStages = append(confStages, conf.PreStages...)
confStages = append(confStages, conf.Stages...) confStages = append(confStages, conf.Stages...)
@ -229,10 +228,24 @@ func MatchGroups(conf *Conf, conventionalCommit *ConventionalCommit) []string {
slog.Info("group keywords from stages", "keywords", keywords) slog.Info("group keywords from stages", "keywords", keywords)
groups := []string{} groups := []string{}
for _, keyword := range keywords { for _, keyword := range keywords {
if strings.Contains(loweredCommitGroup, keyword) { if matchAllGroups || strings.Contains(loweredCommitGroup, keyword) {
groups = append(groups, keyword) groups = append(groups, keyword)
} }
} }
slog.Info("matched groups", "groups", groups) slog.Info("matched groups", "groups", groups)
if matchAllGroups {
for i := range conf.PreStages {
conf.PreStages[i].Group = ""
conf.PreStages[i].Groups = nil
}
for i := range conf.Stages {
conf.Stages[i].Group = ""
conf.Stages[i].Groups = nil
}
for i := range conf.PostStages {
conf.PostStages[i].Group = ""
conf.PostStages[i].Groups = nil
}
}
return groups return groups
} }

18
go.mod
View File

@ -5,15 +5,15 @@ go 1.24.0
toolchain go1.24.1 toolchain go1.24.1
require ( require (
github.com/criyle/go-judge/pb v1.0.0 github.com/criyle/go-judge/pb v1.3.2
github.com/go-git/go-git/v5 v5.16.2 github.com/go-git/go-git/v5 v5.16.5
github.com/jinzhu/copier v0.4.0 github.com/jinzhu/copier v0.4.0
github.com/joint-online-judge/go-gitignore v0.0.0-20250212104351-ad79a46f8dcc github.com/joint-online-judge/go-gitignore v0.0.0-20250212104351-ad79a46f8dcc
github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7 github.com/koding/multiconfig v0.0.0-20171124222453-69c27309b2d7
github.com/mcuadros/go-defaults v1.2.0 github.com/mcuadros/go-defaults v1.2.0
github.com/mitchellh/mapstructure v1.5.0 github.com/mitchellh/mapstructure v1.5.0
google.golang.org/grpc v1.75.1 google.golang.org/grpc v1.79.3
google.golang.org/protobuf v1.36.9 google.golang.org/protobuf v1.36.11
) )
require ( require (
@ -37,11 +37,11 @@ require (
github.com/sergi/go-diff v1.4.0 // indirect github.com/sergi/go-diff v1.4.0 // indirect
github.com/skeema/knownhosts v1.3.1 // indirect github.com/skeema/knownhosts v1.3.1 // indirect
github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect
golang.org/x/crypto v0.43.0 // indirect golang.org/x/crypto v0.46.0 // indirect
golang.org/x/net v0.45.0 // indirect golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.37.0 // indirect golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.30.0 // indirect golang.org/x/text v0.32.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2 // indirect
gopkg.in/warnings.v0 v0.1.2 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect
) )

68
go.sum
View File

@ -11,10 +11,12 @@ github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFI
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0= github.com/cloudflare/circl v1.6.1 h1:zqIqSPIndyBh1bjLVVDHMPpVKqp8Su/V+6MeDzzQBQ0=
github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= github.com/cloudflare/circl v1.6.1/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs=
github.com/criyle/go-judge/pb v1.0.0 h1:8A4zHPPCGCDTuFY1GW5Hqpg+8ETIwzgXxiRpYKKb2zA= github.com/criyle/go-judge/pb v1.3.2 h1:S0c0EqRF+xePOwcZxSb9mPV+bkXgfOX9f7SQMrcdeb4=
github.com/criyle/go-judge/pb v1.0.0/go.mod h1:hjgixgK9NH9ktwc29xbXVdZDOlKfEkRkEbZ4W5bOMmw= github.com/criyle/go-judge/pb v1.3.2/go.mod h1:QfjmF1w4t5ODXikuUcy8Alqb901R6p0HDxJXGKZy0NE=
github.com/cyphar/filepath-securejoin v0.5.0 h1:hIAhkRBMQ8nIeuVwcAoymp7MY4oherZdAxD+m0u9zaw= github.com/cyphar/filepath-securejoin v0.5.0 h1:hIAhkRBMQ8nIeuVwcAoymp7MY4oherZdAxD+m0u9zaw=
github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/cyphar/filepath-securejoin v0.5.0/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI=
github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ= github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964 h1:y5HC9v93H5EPKqaS1UYVg1uYah5Xf51mBfIoWehClUQ=
@ -38,8 +40,8 @@ github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UN
github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII=
github.com/go-git/go-git/v5 v5.16.2 h1:fT6ZIOjE5iEnkzKyxTHK1W4HGAsPhqEqiSAssSO77hM= github.com/go-git/go-git/v5 v5.16.5 h1:mdkuqblwr57kVfXri5TTH+nMFLNUxIj9Z7F5ykFbw5s=
github.com/go-git/go-git/v5 v5.16.2/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= github.com/go-git/go-git/v5 v5.16.5/go.mod h1:QOMLpNf1qxuSY4StA/ArOdfFR2TrKEjJiye2kel2m+M=
github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI=
github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
@ -98,49 +100,51 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM=
github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw=
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64=
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y=
go.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= go.opentelemetry.io/otel v1.39.0 h1:8yPrr/S0ND9QEfTfdP9V+SiwT4E0G7Y5MO7p85nis48=
go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= go.opentelemetry.io/otel v1.39.0/go.mod h1:kLlFTywNWrFyEdH0oj2xK0bFYZtHRYUdv1NklR/tgc8=
go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= go.opentelemetry.io/otel/metric v1.39.0 h1:d1UzonvEZriVfpNKEVmHXbdf909uGTOQjA0HF0Ls5Q0=
go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= go.opentelemetry.io/otel/metric v1.39.0/go.mod h1:jrZSWL33sD7bBxg1xjrqyDjnuzTUB0x1nBERXd7Ftcs=
go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= go.opentelemetry.io/otel/sdk v1.39.0 h1:nMLYcjVsvdui1B/4FRkwjzoRVsMK8uL/cj0OyhKzt18=
go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= go.opentelemetry.io/otel/sdk v1.39.0/go.mod h1:vDojkC4/jsTJsE+kh+LXYQlbL8CgrEcwmt1ENZszdJE=
go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= go.opentelemetry.io/otel/sdk/metric v1.39.0 h1:cXMVVFVgsIf2YL6QkRF4Urbr/aMInf+2WKg+sEJTtB8=
go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= go.opentelemetry.io/otel/sdk/metric v1.39.0/go.mod h1:xq9HEVH7qeX69/JnwEfp6fVq5wosJsY1mt4lLfYdVew=
go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= go.opentelemetry.io/otel/trace v1.39.0 h1:2d2vfpEDmCJ5zVYz7ijaJdOF59xLomrvj7bjt6/qCJI=
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= go.opentelemetry.io/otel/trace v1.39.0/go.mod h1:88w4/PnZSazkGzz/w84VHpQafiU4EtqqlVdxWy+rNOA=
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.43.0 h1:dduJYIi3A3KOfdGOHX8AVZ/jGiyPa3IbBozJ5kNuE04= golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
golang.org/x/crypto v0.43.0/go.mod h1:BFbav4mRNlXJL4wNeejLpWxB7wMbc79PdRGhWKncxR0= golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.45.0 h1:RLBg5JKixCy82FtLJpeNlVM0nrSqpCRYzVU1n8kj0tM= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/net v0.45.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.37.0 h1:fdNQudmxPjkdUTPnLn5mdQv7Zwvbvpaxqs831goi9kQ= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.37.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.36.0 h1:zMPR+aF8gfksFprF/Nc/rd1wRS1EI6nDBGyWAvDzx2Q= golang.org/x/term v0.38.0 h1:PQ5pkm/rLO6HnxFR7N2lJHOZX6Kez5Y1gDSJla6jo7Q=
golang.org/x/term v0.36.0/go.mod h1:Qu394IJq6V6dCBRgwqshf3mPF85AqzYEzofzRdZkWss= golang.org/x/term v0.38.0/go.mod h1:bSEAKrOT1W+VSu9TSCMtoGEOUcKxOKgl3LE5QEF/xVg=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.30.0 h1:yznKA/E9zq54KzlzBEAWn1NXSQ8DIp/NYMy88xJjl4k= golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.30.0/go.mod h1:yDdHFIX9t+tORqspjENWgzaCVXgk0yYnYuSZ8UzzBVM= golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk=
gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4 h1:i8QOKZfYg6AbGVZzUAY3LrNWCKF8O6zFisU9Wl9RER4= google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2 h1:2I6GHUeJ/4shcDpoUlLs/2WPnhg7yJwvXtqcMJt9liA=
google.golang.org/genproto/googleapis/rpc v0.0.0-20250929231259-57b25ae835d4/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/genproto/googleapis/rpc v0.0.0-20251213004720-97cd9d5aeac2/go.mod h1:7i2o+ce6H/6BluujYR+kqX3GKH+dChPTQU19wjRPiGk=
google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= google.golang.org/grpc v1.79.1 h1:zGhSi45ODB9/p3VAawt9a+O/MULLl9dpizzNNpq7flY=
google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc v1.79.1/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= google.golang.org/grpc v1.79.3 h1:sybAEdRIEtvcD68Gx7dmnwjZKlyfuc61Dyo9pGXXkKE=
google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= google.golang.org/grpc v1.79.3/go.mod h1:KmT0Kjez+0dde/v2j9vzwoAScgEPx/Bw1CYChhHLrHQ=
google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE=
google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -8,33 +8,34 @@ import (
"github.com/criyle/go-judge/pb" "github.com/criyle/go-judge/pb"
"github.com/joint-online-judge/JOJ3/internal/stage" "github.com/joint-online-judge/JOJ3/internal/stage"
"google.golang.org/protobuf/types/known/emptypb"
) )
// copied from https://github.com/criyle/go-judge/blob/master/cmd/go-judge-shell/grpc.go // copied from https://github.com/criyle/go-judge/blob/master/cmd/go-judge-shell/grpc.go
func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType { func convertPBCmd(cmd []stage.Cmd) []*pb.Request_CmdType {
ret := make([]*pb.Request_CmdType, 0, len(cmd)) ret := make([]*pb.Request_CmdType, 0, len(cmd))
for _, c := range cmd { for _, c := range cmd {
ret = append(ret, &pb.Request_CmdType{ req := &pb.Request_CmdType{}
Args: c.Args, req.SetArgs(c.Args)
Env: c.Env, req.SetEnv(c.Env)
Tty: c.TTY, req.SetTty(c.TTY)
Files: convertPBFiles([]*stage.CmdFile{c.Stdin, c.Stdout, c.Stderr}), req.SetFiles(convertPBFiles([]*stage.CmdFile{c.Stdin, c.Stdout, c.Stderr}))
CpuTimeLimit: c.CPULimit, req.SetCpuTimeLimit(c.CPULimit)
ClockTimeLimit: c.ClockLimit, req.SetClockTimeLimit(c.ClockLimit)
MemoryLimit: c.MemoryLimit, req.SetMemoryLimit(c.MemoryLimit)
StackLimit: c.StackLimit, req.SetStackLimit(c.StackLimit)
ProcLimit: c.ProcLimit, req.SetProcLimit(c.ProcLimit)
CpuRateLimit: c.CPURateLimit, req.SetCpuRateLimit(c.CPURateLimit)
CpuSetLimit: c.CPUSetLimit, req.SetCpuSetLimit(c.CPUSetLimit)
DataSegmentLimit: c.DataSegmentLimit, req.SetDataSegmentLimit(c.DataSegmentLimit)
AddressSpaceLimit: c.AddressSpaceLimit, req.SetAddressSpaceLimit(c.AddressSpaceLimit)
CopyIn: convertPBCopyIn(c.CopyIn, c.CopyInDir), req.SetCopyIn(convertPBCopyIn(c.CopyIn, c.CopyInDir))
CopyOut: convertPBCopyOut(c.CopyOut), req.SetCopyOut(convertPBCopyOut(c.CopyOut))
CopyOutCached: convertPBCopyOut(c.CopyOutCached), req.SetCopyOutCached(convertPBCopyOut(c.CopyOutCached))
CopyOutMax: c.CopyOutMax, req.SetCopyOutMax(c.CopyOutMax)
CopyOutDir: c.CopyOutDir, req.SetCopyOutDir(c.CopyOutDir)
Symlinks: convertSymlink(c.CopyIn), req.SetSymlinks(convertSymlink(c.CopyIn))
}) ret = append(ret, req)
} }
return ret return ret
} }
@ -81,10 +82,10 @@ func convertPBCopyOut(copyOut []string) []*pb.Request_CmdCopyOutFile {
optional = true optional = true
n = strings.TrimSuffix(n, "?") n = strings.TrimSuffix(n, "?")
} }
rt = append(rt, &pb.Request_CmdCopyOutFile{ elem := &pb.Request_CmdCopyOutFile{}
Name: n, elem.SetName(n)
Optional: optional, elem.SetOptional(optional)
}) rt = append(rt, elem)
} }
return rt return rt
} }
@ -113,6 +114,7 @@ func convertPBFiles(files []*stage.CmdFile) []*pb.Request_File {
} }
func convertPBFile(i stage.CmdFile) *pb.Request_File { func convertPBFile(i stage.CmdFile) *pb.Request_File {
req := &pb.Request_File{}
switch { switch {
case i.Src != nil: case i.Src != nil:
if !filepath.IsAbs(*i.Src) { if !filepath.IsAbs(*i.Src) {
@ -128,18 +130,34 @@ func convertPBFile(i stage.CmdFile) *pb.Request_File {
s = []byte{} s = []byte{}
slog.Error("convert pb file read file", "path", *i.Src, "error", err) slog.Error("convert pb file read file", "path", *i.Src, "error", err)
} }
return &pb.Request_File{File: &pb.Request_File_Memory{Memory: &pb.Request_MemoryFile{Content: s}}} m := &pb.Request_MemoryFile{}
m.SetContent(s)
req.SetMemory(m)
return req
case i.Content != nil: case i.Content != nil:
s := strToBytes(*i.Content) s := strToBytes(*i.Content)
return &pb.Request_File{File: &pb.Request_File_Memory{Memory: &pb.Request_MemoryFile{Content: s}}} m := &pb.Request_MemoryFile{}
m.SetContent(s)
req.SetMemory(m)
return req
case i.FileID != nil: case i.FileID != nil:
return &pb.Request_File{File: &pb.Request_File_Cached{Cached: &pb.Request_CachedFile{FileID: *i.FileID}}} c := &pb.Request_CachedFile{}
c.SetFileID(*i.FileID)
req.SetCached(c)
return req
case i.Name != nil && i.Max != nil: case i.Name != nil && i.Max != nil:
return &pb.Request_File{File: &pb.Request_File_Pipe{Pipe: &pb.Request_PipeCollector{Name: *i.Name, Max: *i.Max, Pipe: i.Pipe}}} p := &pb.Request_PipeCollector{}
p.SetName(*i.Name)
p.SetMax(*i.Max)
p.SetPipe(i.Pipe)
req.SetPipe(p)
return req
case i.StreamIn: case i.StreamIn:
return &pb.Request_File{File: &pb.Request_File_StreamIn{}} req.SetStreamIn(&emptypb.Empty{})
return req
case i.StreamOut: case i.StreamOut:
return &pb.Request_File{File: &pb.Request_File_StreamOut{}} req.SetStreamOut(&emptypb.Empty{})
return req
} }
return nil return nil
} }
@ -148,17 +166,17 @@ func convertPBResult(res []*pb.Response_Result) []stage.ExecutorResult {
ret := make([]stage.ExecutorResult, 0, len(res)) ret := make([]stage.ExecutorResult, 0, len(res))
for _, r := range res { for _, r := range res {
ret = append(ret, stage.ExecutorResult{ ret = append(ret, stage.ExecutorResult{
Status: stage.Status(r.Status), Status: stage.Status(r.GetStatus()),
ExitStatus: int(r.ExitStatus), ExitStatus: int(r.GetExitStatus()),
Error: r.Error, Error: r.GetError(),
Time: r.Time, Time: r.GetTime(),
Memory: r.Memory, Memory: r.GetMemory(),
RunTime: r.RunTime, RunTime: r.GetRunTime(),
ProcPeak: r.ProcPeak, ProcPeak: r.GetProcPeak(),
Files: convertFiles(r.Files), Files: convertFiles(r.GetFiles()),
Buffs: r.Files, Buffs: r.GetFiles(),
FileIDs: r.FileIDs, FileIDs: r.GetFileIDs(),
FileError: convertPBFileError(r.FileError), FileError: convertPBFileError(r.GetFileError()),
}) })
} }
return ret return ret
@ -176,9 +194,9 @@ func convertPBFileError(fe []*pb.Response_FileError) []stage.FileError {
ret := make([]stage.FileError, 0, len(fe)) ret := make([]stage.FileError, 0, len(fe))
for _, v := range fe { for _, v := range fe {
ret = append(ret, stage.FileError{ ret = append(ret, stage.FileError{
Name: v.Name, Name: v.GetName(),
Type: stage.FileErrorType(v.Type), Type: stage.FileErrorType(v.GetType()),
Message: v.Message, Message: v.GetMessage(),
}) })
} }
return ret return ret

View File

@ -36,16 +36,17 @@ func (e *Sandbox) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
for i, pbCmd := range pbCmds { for i, pbCmd := range pbCmds {
slog.Debug("sandbox execute", "i", i, "pbCmd size", proto.Size(pbCmd)) slog.Debug("sandbox execute", "i", i, "pbCmd size", proto.Size(pbCmd))
} }
pbReq := &pb.Request{Cmd: pbCmds} pbReq := &pb.Request{}
pbReq.SetCmd(pbCmds)
slog.Debug("sandbox execute", "pbReq size", proto.Size(pbReq)) slog.Debug("sandbox execute", "pbReq size", proto.Size(pbReq))
pbRet, err := e.execClient.Exec(context.TODO(), pbReq) pbRet, err := e.execClient.Exec(context.TODO(), pbReq)
if err != nil { if err != nil {
return nil, err return nil, err
} }
if pbRet.Error != "" { if pbRet.GetError() != "" {
return nil, fmt.Errorf("sandbox execute error: %s", pbRet.Error) return nil, fmt.Errorf("sandbox execute error: %s", pbRet.GetError())
} }
results := convertPBResult(pbRet.Results) results := convertPBResult(pbRet.GetResults())
for _, result := range results { for _, result := range results {
maps.Copy(e.cachedMap, result.FileIDs) maps.Copy(e.cachedMap, result.FileIDs)
} }
@ -54,9 +55,9 @@ func (e *Sandbox) Run(cmds []stage.Cmd) ([]stage.ExecutorResult, error) {
func (e *Sandbox) Cleanup() error { func (e *Sandbox) Cleanup() error {
for k, fileID := range e.cachedMap { for k, fileID := range e.cachedMap {
_, err := e.execClient.FileDelete(context.TODO(), &pb.FileID{ req := &pb.FileID{}
FileID: fileID, req.SetFileID(fileID)
}) _, err := e.execClient.FileDelete(context.TODO(), req)
if err != nil { if err != nil {
slog.Error("sandbox cleanup", "error", err) slog.Error("sandbox cleanup", "error", err)
} }

View File

@ -5,31 +5,48 @@ import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"log/slog" "log/slog"
"strings"
"github.com/joint-online-judge/JOJ3/internal/stage" "github.com/joint-online-judge/JOJ3/internal/stage"
) )
func (*Log) parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult { func (*Log) parse(executorResult stage.ExecutorResult, conf Conf) stage.ParserResult {
content := executorResult.Files[conf.Filename] content, ok := executorResult.Files[conf.Filename]
var data map[string]any if !ok {
err := json.Unmarshal([]byte(content), &data) slog.Error("file not found for log parser", "filename", conf.Filename)
if err != nil {
slog.Error(conf.Msg, "error", err)
return stage.ParserResult{ return stage.ParserResult{
Score: 0, Score: 0,
Comment: fmt.Sprintf("Failed to parse content: %s", err), Comment: fmt.Sprintf("log parser: file %s not found", conf.Filename),
} }
} }
args := make([]any, 0, len(data)*2) contentBytes := []byte(content)
for key, value := range data { var data map[string]any
args = append(args, key, value) if err := json.Unmarshal(contentBytes, &data); err != nil {
// Not a valid json or failed to unmarshal, log as raw string line by line.
for line := range strings.SplitSeq(content, "\n") {
if strings.TrimSpace(line) != "" {
slog.Default().Log(
context.Background(),
slog.Level(conf.Level),
conf.Msg,
"line",
line,
)
}
}
} else {
// Valid json, log as key-value pairs.
args := make([]any, 0, len(data)*2)
for key, value := range data {
args = append(args, key, value)
}
slog.Default().Log(
context.Background(),
slog.Level(conf.Level),
conf.Msg,
args...,
)
} }
slog.Default().Log(
context.Background(),
slog.Level(conf.Level),
conf.Msg,
args...,
)
return stage.ParserResult{ return stage.ParserResult{
Score: 0, Score: 0,
Comment: "", Comment: "",