diff --git a/cmd/imports/daemon.go b/cmd/imports/daemon.go
index 31ac9226..ea62ccb3 100644
--- a/cmd/imports/daemon.go
+++ b/cmd/imports/daemon.go
@@ -21,4 +21,6 @@ import (
_ "github.com/go-sigma/sigma/pkg/daemon/gc"
_ "github.com/go-sigma/sigma/pkg/daemon/sbom"
_ "github.com/go-sigma/sigma/pkg/daemon/vulnerability"
+ _ "github.com/go-sigma/sigma/pkg/workq/database"
+ _ "github.com/go-sigma/sigma/pkg/workq/kafka"
)
diff --git a/cmd/server.go b/cmd/server.go
index 6c5ad9f9..f74b0d0a 100644
--- a/cmd/server.go
+++ b/cmd/server.go
@@ -30,7 +30,7 @@ import (
// serverCmd represents the server command
var serverCmd = &cobra.Command{
Use: "server",
- Short: "Start the XImager server",
+ Short: "Start the sigma server",
PersistentPreRun: func(_ *cobra.Command, _ []string) {
initConfig()
logger.SetLevel(viper.GetString("log.level"))
diff --git a/cmd/version.go b/cmd/version.go
index bd448ba4..980a5a0a 100644
--- a/cmd/version.go
+++ b/cmd/version.go
@@ -22,30 +22,32 @@ import (
"github.com/spf13/cobra"
)
+// You can copy & paste this ascii graphic and use it e.g. as mail signature
+// Font: doh Reflection: no Adjustment: left Stretch: no Width: 280 Text: sigma
const banner = `
-XXXXXXX XXXXXXIIIIIIIIII
-X:::::X X:::::I::::::::I
-X:::::X X:::::I::::::::I
-X::::::X X::::::II::::::II
-XXX:::::X X:::::XXX I::::I mmmmmmm mmmmmmm aaaaaaaaaaaaa ggggggggg ggggg eeeeeeeeeeee rrrrr rrrrrrrrr
- X:::::X X:::::X I::::I mm:::::::m m:::::::mm a::::::::::::a g:::::::::ggg::::g ee::::::::::::ee r::::rrr:::::::::r
- X:::::X:::::X I::::I m::::::::::mm::::::::::m aaaaaaaaa:::::ag:::::::::::::::::ge::::::eeeee:::::er:::::::::::::::::r
- X:::::::::X I::::I m::::::::::::::::::::::m a::::g::::::ggggg::::::ge::::::e e:::::rr::::::rrrrr::::::r
- X:::::::::X I::::I m:::::mmm::::::mmm:::::m aaaaaaa:::::g:::::g g:::::ge:::::::eeeee::::::er:::::r r:::::r
- X:::::X:::::X I::::I m::::m m::::m m::::m aa::::::::::::g:::::g g:::::ge:::::::::::::::::e r:::::r rrrrrrr
- X:::::X X:::::X I::::I m::::m m::::m m::::ma::::aaaa::::::g:::::g g:::::ge::::::eeeeeeeeeee r:::::r
-XXX:::::X X:::::XXX I::::I m::::m m::::m m::::a::::a a:::::g::::::g g:::::ge:::::::e r:::::r
-X::::::X X::::::II::::::Im::::m m::::m m::::a::::a a:::::g:::::::ggggg:::::ge::::::::e r:::::r
-X:::::X X:::::I::::::::m::::m m::::m m::::a:::::aaaa::::::ag::::::::::::::::g e::::::::eeeeeeee r:::::r
-X:::::X X:::::I::::::::m::::m m::::m m::::ma::::::::::aa:::agg::::::::::::::g ee:::::::::::::e r:::::r
-XXXXXXX XXXXXXIIIIIIIIImmmmmm mmmmmm mmmmmm aaaaaaaaaa aaaa gggggggg::::::g eeeeeeeeeeeeee rrrrrrr
- g:::::g
- gggggg g:::::g
- g:::::gg gg:::::g
- g::::::ggg:::::::g
- gg:::::::::::::g
- ggg::::::ggg
- gggggg`
+ iiii
+ i::::i
+ iiii
+
+ ssssssssss iiiiiii ggggggggg ggggg mmmmmmm mmmmmmm aaaaaaaaaaaaa
+ ss::::::::::s i:::::i g:::::::::ggg::::g mm:::::::m m:::::::mm a::::::::::::a
+ss:::::::::::::s i::::i g:::::::::::::::::gm::::::::::mm::::::::::m aaaaaaaaa:::::a
+s::::::ssss:::::s i::::i g::::::ggggg::::::ggm::::::::::::::::::::::m a::::a
+ s:::::s ssssss i::::i g:::::g g:::::g m:::::mmm::::::mmm:::::m aaaaaaa:::::a
+ s::::::s i::::i g:::::g g:::::g m::::m m::::m m::::m aa::::::::::::a
+ s::::::s i::::i g:::::g g:::::g m::::m m::::m m::::m a::::aaaa::::::a
+ssssss s:::::s i::::i g::::::g g:::::g m::::m m::::m m::::ma::::a a:::::a
+s:::::ssss::::::si::::::ig:::::::ggggg:::::g m::::m m::::m m::::ma::::a a:::::a
+s::::::::::::::s i::::::i g::::::::::::::::g m::::m m::::m m::::ma:::::aaaa::::::a
+ s:::::::::::ss i::::::i gg::::::::::::::g m::::m m::::m m::::m a::::::::::aa:::a
+ sssssssssss iiiiiiii gggggggg::::::g mmmmmm mmmmmm mmmmmm aaaaaaaaaa aaaa
+ g:::::g
+ gggggg g:::::g
+ g:::::gg gg:::::g
+ g::::::ggg:::::::g
+ gg:::::::::::::g
+ ggg::::::ggg
+ gggggg`
var (
version = ""
@@ -56,7 +58,7 @@ var (
// versionCmd represents the worker command
var versionCmd = &cobra.Command{
Use: "version",
- Short: "Show version of XImager",
+ Short: "Show version of sigma",
Run: func(_ *cobra.Command, _ []string) {
color.Cyan(banner)
fmt.Printf("Version: %s\n", version)
diff --git a/cmd/worker.go b/cmd/worker.go
index f45b4b5d..cfc89736 100644
--- a/cmd/worker.go
+++ b/cmd/worker.go
@@ -29,7 +29,7 @@ import (
// workerCmd represents the worker command
var workerCmd = &cobra.Command{
Use: "worker",
- Short: "Start the XImager worker",
+ Short: "Start the sigma worker",
PersistentPreRun: func(_ *cobra.Command, _ []string) {
initConfig()
logger.SetLevel(viper.GetString("log.level"))
diff --git a/go.mod b/go.mod
index 09be766d..90abe4fb 100644
--- a/go.mod
+++ b/go.mod
@@ -5,25 +5,26 @@ go 1.20
require (
code.gitea.io/sdk/gitea v0.16.0
github.com/BurntSushi/toml v1.3.2
+ github.com/IBM/sarama v1.41.2
github.com/Masterminds/sprig/v3 v3.2.3
github.com/alicebob/miniredis/v2 v2.30.5
github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible
github.com/anchore/syft v0.90.0
- github.com/aquasecurity/trivy v0.45.0
- github.com/aws/aws-sdk-go v1.45.7
+ github.com/aquasecurity/trivy v0.45.1
+ github.com/aws/aws-sdk-go v1.45.11
github.com/bytedance/json v0.0.0-20190516032711-0d89175f1949
github.com/caarlos0/env/v9 v9.0.0
github.com/casbin/casbin/v2 v2.77.2
github.com/casbin/gorm-adapter/v3 v3.19.0
github.com/deckarep/golang-set/v2 v2.3.1
- github.com/distribution/distribution/v3 v3.0.0-20230908093250-285b601af99a
+ github.com/distribution/distribution/v3 v3.0.0-20230915083636-612ad42609c3
github.com/distribution/reference v0.5.0
github.com/docker/cli v24.0.6+incompatible
github.com/docker/docker v24.0.6+incompatible
github.com/dustin/go-humanize v1.0.1
github.com/fatih/color v1.15.0
github.com/glebarez/sqlite v1.9.0
- github.com/go-git/go-git/v5 v5.8.1
+ github.com/go-git/go-git/v5 v5.9.0
github.com/go-playground/validator v9.31.0+incompatible
github.com/go-redsync/redsync/v4 v4.9.4
github.com/go-resty/resty/v2 v2.7.0
@@ -55,7 +56,7 @@ require (
github.com/tidwall/gjson v1.16.0
github.com/wagslane/go-password-validator v0.3.0
github.com/xanzy/go-gitlab v0.91.1
- go.uber.org/mock v0.2.0
+ go.uber.org/mock v0.3.0
golang.org/x/crypto v0.13.0
golang.org/x/exp v0.0.0-20230905200255-921286631fa9
golang.org/x/oauth2 v0.12.0
@@ -66,22 +67,8 @@ require (
gorm.io/gorm v1.25.4
gorm.io/plugin/dbresolver v1.4.7
gorm.io/plugin/soft_delete v1.2.1
- k8s.io/api v0.28.1
- k8s.io/client-go v0.28.1
-)
-
-require (
- github.com/adrg/xdg v0.4.0 // indirect
- github.com/anchore/clio v0.0.0-20230823172630-c42d666061af // indirect
- github.com/anchore/fangs v0.0.0-20230818131516-2186b10924fe // indirect
- github.com/felixge/fgprof v0.9.3 // indirect
- github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
- github.com/gookit/color v1.5.4 // indirect
- github.com/iancoleman/strcase v0.3.0 // indirect
- github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
- github.com/pborman/indent v1.2.1 // indirect
- github.com/pkg/profile v1.7.0 // indirect
- github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
+ k8s.io/api v0.28.2
+ k8s.io/client-go v0.28.2
)
require (
@@ -90,10 +77,13 @@ require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.2.1 // indirect
github.com/Microsoft/go-winio v0.6.1 // indirect
- github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 // indirect
+ github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/acobaugh/osrelease v0.1.0 // indirect
github.com/acomagu/bufpipe v1.0.4 // indirect
+ github.com/adrg/xdg v0.4.0 // indirect
github.com/alicebob/gopher-json v0.0.0-20230218143504-906a9b012302 // indirect
+ github.com/anchore/clio v0.0.0-20230823172630-c42d666061af // indirect
+ github.com/anchore/fangs v0.0.0-20230818131516-2186b10924fe // indirect
github.com/anchore/go-logger v0.0.0-20230725134548-c21dafa1ec5a // indirect
github.com/anchore/go-struct-converter v0.0.0-20230627203149-c72ef8859ca9 // indirect
github.com/anchore/packageurl-go v0.1.1-0.20230104203445-02e0a6721501 // indirect
@@ -105,8 +95,9 @@ require (
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/cloudflare/circl v1.3.3 // indirect
- github.com/containerd/containerd v1.7.3 // indirect
+ github.com/containerd/containerd v1.7.5 // indirect
github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect
+ github.com/cyphar/filepath-securejoin v0.2.4 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/davidmz/go-pageant v1.0.2 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
@@ -115,8 +106,12 @@ require (
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
+ github.com/eapache/go-resiliency v1.4.0 // indirect
+ github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
+ github.com/eapache/queue v1.1.0 // indirect
github.com/emicklei/go-restful/v3 v3.10.2 // indirect
github.com/facebookincubator/nvdtools v0.1.5 // indirect
+ github.com/felixge/fgprof v0.9.3 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
@@ -124,7 +119,7 @@ require (
github.com/glebarez/go-sqlite v1.21.2 // indirect
github.com/go-fed/httpsig v1.1.0 // indirect
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
- github.com/go-git/go-billy/v5 v5.4.1 // indirect
+ github.com/go-git/go-billy/v5 v5.5.0 // indirect
github.com/go-logr/logr v1.2.4 // indirect
github.com/go-ole/go-ole v1.3.0 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
@@ -145,14 +140,18 @@ require (
github.com/google/go-containerregistry v0.16.1 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
+ github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
+ github.com/gookit/color v1.5.4 // indirect
github.com/gopherjs/gopherjs v1.17.2 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/hashicorp/go-retryablehttp v0.7.4 // indirect
+ github.com/hashicorp/go-uuid v1.0.3 // indirect
github.com/hashicorp/go-version v1.6.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
+ github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.16 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jackc/chunkreader/v2 v2.0.1 // indirect
@@ -164,6 +163,11 @@ require (
github.com/jackc/pgtype v1.14.0 // indirect
github.com/jackc/pgx/v5 v5.4.3 // indirect
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect
+ github.com/jcmturner/aescts/v2 v2.0.0 // indirect
+ github.com/jcmturner/dnsutils/v2 v2.0.0 // indirect
+ github.com/jcmturner/gofork v1.7.6 // indirect
+ github.com/jcmturner/gokrb5/v8 v8.4.4 // indirect
+ github.com/jcmturner/rpc/v2 v2.0.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
@@ -181,6 +185,7 @@ require (
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/mattn/go-sqlite3 v1.14.17 // indirect
+ github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
github.com/mholt/archiver/v3 v3.5.1
github.com/microsoft/go-mssqldb v1.5.0 // indirect
github.com/mitchellh/copystructure v1.2.0 // indirect
@@ -194,13 +199,16 @@ require (
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect
github.com/opencontainers/image-spec v1.1.0-rc4 // indirect
+ github.com/pborman/indent v1.2.1 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pelletier/go-toml/v2 v2.0.9 // indirect
github.com/pierrec/lz4/v4 v4.1.18 // indirect
github.com/pjbgf/sha1cd v0.3.0 // indirect
github.com/pkg/errors v0.9.1 // indirect
+ github.com/pkg/profile v1.7.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
+ github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/scylladb/go-set v1.0.3-0.20200225121959-cc7b2070d91e // indirect
@@ -229,6 +237,7 @@ require (
github.com/wagoodman/go-partybus v0.0.0-20230516145632-8ccac152c651 // indirect
github.com/wagoodman/go-progress v0.0.0-20230301185719-21920a456ad5 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
+ github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect
github.com/yuin/gopher-lua v1.1.0 // indirect
github.com/yusufpapurcu/wmi v1.2.3 // indirect
go.uber.org/atomic v1.11.0 // indirect
@@ -254,7 +263,7 @@ require (
gorm.io/datatypes v1.2.0 // indirect
gorm.io/driver/sqlserver v1.5.1 // indirect
gorm.io/hints v1.1.2 // indirect
- k8s.io/apimachinery v0.28.1
+ k8s.io/apimachinery v0.28.2
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 // indirect
k8s.io/utils v0.0.0-20230726121419-3b25d923346b // indirect
diff --git a/go.sum b/go.sum
index b2c8dbd3..54810de9 100644
--- a/go.sum
+++ b/go.sum
@@ -62,6 +62,8 @@ github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
+github.com/IBM/sarama v1.41.2 h1:ZDBZfGPHAD4uuAtSv4U22fRZBgst0eEwGFzLj0fb85c=
+github.com/IBM/sarama v1.41.2/go.mod h1:xdpu7sd6OE1uxNdjYTSKUfY8FaKkJES9/+EyjSgiGQk=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
@@ -77,8 +79,8 @@ github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBa
github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow=
github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95 h1:KLq8BE0KwCL+mmXnjLWEAOYO+2l2AE4YMmqG1ZpZHBs=
-github.com/ProtonMail/go-crypto v0.0.0-20230717121422-5aa5874ade95/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
+github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg=
+github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0=
github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM=
github.com/acobaugh/osrelease v0.1.0 h1:Yb59HQDGGNhCj4suHaFQQfBps5wyoKLSSX/J/+UifRE=
github.com/acobaugh/osrelease v0.1.0/go.mod h1:4bFEs0MtgHNHBrmHCt67gNisnabCRAlzdVasCEGHTWY=
@@ -119,8 +121,8 @@ github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/aquasecurity/trivy v0.45.0 h1:Pwla4x6G2U2xrcsfsrdeZmLUmnrFPlUhg23xcNTzJX8=
-github.com/aquasecurity/trivy v0.45.0/go.mod h1:nqruwuHFYfEDw4UGeg0oAzgAHYAtMpUR/PNfVDTidF4=
+github.com/aquasecurity/trivy v0.45.1 h1:JjkrawgNpVUV6mxtFX635I3MhzDqmGkze46SnygkYN0=
+github.com/aquasecurity/trivy v0.45.1/go.mod h1:3cawI6q9o32pPGXhuGEIWWwUCSMAzRk/FhsEdA4eW1k=
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917 h1:MQd7h7yUyA8UlUzhjNMzpUX0NpD7jfxmRfSKwp/Ji3E=
github.com/aquasecurity/trivy-db v0.0.0-20230831170347-f732860d4917/go.mod h1:WJ5Qnk5ZNGWvks07GOZe2IOsuXrPfSC5c8hYGOGfrsU=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
@@ -128,8 +130,8 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/aws/aws-sdk-go v1.45.7 h1:k4QsvWZhm8409TYeRuTV1P6+j3lLKoe+giFA/j3VAps=
-github.com/aws/aws-sdk-go v1.45.7/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
+github.com/aws/aws-sdk-go v1.45.11 h1:8qiSrA12+NRr+2MVpMApi3JxtiFFjDVU1NeWe+80bYg=
+github.com/aws/aws-sdk-go v1.45.11/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/becheran/wildmatch-go v1.0.0 h1:mE3dGGkTmpKtT4Z+88t8RStG40yN9T+kFEGj2PZFSzA=
github.com/becheran/wildmatch-go v1.0.0/go.mod h1:gbMvj0NtVdJ15Mg/mH9uxk2R1QCistMyU7d9KFzroX4=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -182,8 +184,8 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I=
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
-github.com/containerd/containerd v1.7.3 h1:cKwYKkP1eTj54bP3wCdXXBymmKRQMrWjkLSWZZJDa8o=
-github.com/containerd/containerd v1.7.3/go.mod h1:32FOM4/O0RkNg7AjQj3hDzN9cUGtu+HMvaKUNiqCZB8=
+github.com/containerd/containerd v1.7.5 h1:i9T9XpAWMe11BHMN7pu1BZqOGjXaKTPyz2v+KYOZgkY=
+github.com/containerd/containerd v1.7.5/go.mod h1:ieJNCSzASw2shSGYLHx8NAE7WsZ/gEigo5fQ78W5Zvw=
github.com/containerd/stargz-snapshotter/estargz v0.14.3 h1:OqlDCK3ZVUO6C3B/5FSkDwbkEETK84kQgEeFwDC+62k=
github.com/containerd/stargz-snapshotter/estargz v0.14.3/go.mod h1:KY//uOCIkSuNAHhJogcZtrNHdKrA99/FCCRjE3HD36o=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
@@ -195,6 +197,8 @@ github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg=
+github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -206,8 +210,8 @@ github.com/dgrijalva/jwt-go/v4 v4.0.0-preview1/go.mod h1:+hnT3ywWDTAFrW5aE+u2Sa/
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/dhui/dktest v0.3.16 h1:i6gq2YQEtcrjKbeJpBkWjE8MmLZPYllcjOFbTZuPDnw=
-github.com/distribution/distribution/v3 v3.0.0-20230908093250-285b601af99a h1:UCizW/swHK+zxiZfXcrKybLRhm0pou8gJFNXeH7Xb5Y=
-github.com/distribution/distribution/v3 v3.0.0-20230908093250-285b601af99a/go.mod h1:kwpPDTHXOnL7Ei4I8QaP0rOH/KP9SYIuXABAvv5jw0c=
+github.com/distribution/distribution/v3 v3.0.0-20230915083636-612ad42609c3 h1:NNbaD3nHlCm6c6trUVsYrQqDTsR8sDPaZKJOgZ6PFn8=
+github.com/distribution/distribution/v3 v3.0.0-20230915083636-612ad42609c3/go.mod h1:kwpPDTHXOnL7Ei4I8QaP0rOH/KP9SYIuXABAvv5jw0c=
github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0=
github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E=
github.com/dnaeon/go-vcr v1.1.0/go.mod h1:M7tiix8f0r6mKKJ3Yq/kqU1OYf3MnfmBWVbPx/yU9ko=
@@ -229,6 +233,12 @@ github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj6
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
+github.com/eapache/go-resiliency v1.4.0 h1:3OK9bWpPk5q6pbFAaYSEwD9CLUSHG8bnZuqX2yMt3B0=
+github.com/eapache/go-resiliency v1.4.0/go.mod h1:5yPzW0MIvSe0JDsv0v+DvcjEv2FyD6iZYSs1ZI+iQho=
+github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4ALJ04o5Qqpdz8XLIpNA3WM/iSIXqxtqo7UGVws=
+github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
+github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/emicklei/go-restful/v3 v3.10.2 h1:hIovbnmBTLjHXkqEBUz3HGpXZdM7ZrE9fJIZIqlJLqE=
github.com/emicklei/go-restful/v3 v3.10.2/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -254,6 +264,7 @@ github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA=
github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI=
github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g=
github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw=
+github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/frankban/quicktest v1.14.4 h1:g2rn0vABPOOXmZUj+vbmUp0lPoXEMuhTpIluN0XL9UY=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@@ -274,11 +285,11 @@ github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI=
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic=
-github.com/go-git/go-billy/v5 v5.4.1 h1:Uwp5tDRkPr+l/TnbHOQzp+tmJfLceOlbVucgpTz8ix4=
-github.com/go-git/go-billy/v5 v5.4.1/go.mod h1:vjbugF6Fz7JIflbVpl1hJsGjSHNltrSw45YK/ukIvQg=
+github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU=
+github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow=
github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20230305113008-0c11038e723f h1:Pz0DHeFij3XFhoBRGUDPzSJ+w2UcK5/0JvF8DRI58r8=
-github.com/go-git/go-git/v5 v5.8.1 h1:Zo79E4p7TRk0xoRgMq0RShiTHGKcKI4+DI6BfJc/Q+A=
-github.com/go-git/go-git/v5 v5.8.1/go.mod h1:FHFuoD6yGz5OSKEBK+aWN9Oah0q54Jxl0abmj6GnqAo=
+github.com/go-git/go-git/v5 v5.9.0 h1:cD9SFA7sHVRdJ7AYck1ZaAa/yeuBvGPxwXDL8cxrObY=
+github.com/go-git/go-git/v5 v5.9.0/go.mod h1:RKIqga24sWdMGZF+1Ekv9kylsDz6LzdTSI2s/OsZWE0=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
@@ -495,6 +506,7 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v1.5.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek=
@@ -582,11 +594,17 @@ github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dv
github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A=
github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo=
+github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
+github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
+github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
+github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
+github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
+github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jinzhu/copier v0.4.0 h1:w3ciUoD19shMCRargcpm0cm91ytaBhDvuRpz1ODO/U8=
github.com/jinzhu/copier v0.4.0/go.mod h1:DfbEm0FYsaqBcKcFuvmOZb218JkPGtvSHsKg8S8hyyg=
@@ -775,7 +793,7 @@ github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2
github.com/onsi/gomega v1.24.1/go.mod h1:3AOiACssS3/MajrniINInwbfOOtfZvplPzuRSmvt1jM=
github.com/onsi/gomega v1.25.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
github.com/onsi/gomega v1.26.0/go.mod h1:r+zV744Re+DiYCIPRlYOTxn0YkOLcAnW8k1xXdMPGhM=
-github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE=
+github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI=
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20230727214836-6bc87156eacf h1:UyoZ/WziSy7+CIWLfn68zhJkJqIin10U0wkL2FUNRCM=
github.com/opencontainers/distribution-spec/specs-go v0.0.0-20230727214836-6bc87156eacf/go.mod h1:Va0IMqkjv62YSEytL4sgxrkiD9IzU0T0bX/ZZEtMnSQ=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
@@ -825,6 +843,8 @@ github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8b
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
+github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/redis/go-redis/v9 v9.0.2/go.mod h1:/xDTe9EF1LM61hek62Poq2nzQSGj0xSrEtEHbBQevps=
github.com/redis/go-redis/v9 v9.0.3/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk=
github.com/redis/go-redis/v9 v9.1.0 h1:137FnGdk+EQdCbye1FW+qOEcY5S+SpY9T0NiuqvtfMY=
@@ -1013,8 +1033,8 @@ go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0
go.uber.org/goleak v1.1.12/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo=
-go.uber.org/mock v0.2.0 h1:TaP3xedm7JaAgScZO7tlvlKrqT0p7I6OsdGB5YNSMDU=
-go.uber.org/mock v0.2.0/go.mod h1:J0y0rp9L3xiff1+ZBfKxlC1fz2+aO16tw0tsDOixfuM=
+go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
+go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
@@ -1631,12 +1651,12 @@ honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.28.1 h1:i+0O8k2NPBCPYaMB+uCkseEbawEt/eFaiRqUx8aB108=
-k8s.io/api v0.28.1/go.mod h1:uBYwID+66wiL28Kn2tBjBYQdEU0Xk0z5qF8bIBqk/Dg=
-k8s.io/apimachinery v0.28.1 h1:EJD40og3GizBSV3mkIoXQBsws32okPOy+MkRyzh6nPY=
-k8s.io/apimachinery v0.28.1/go.mod h1:X0xh/chESs2hP9koe+SdIAcXWcQ+RM5hy0ZynB+yEvw=
-k8s.io/client-go v0.28.1 h1:pRhMzB8HyLfVwpngWKE8hDcXRqifh1ga2Z/PU9SXVK8=
-k8s.io/client-go v0.28.1/go.mod h1:pEZA3FqOsVkCc07pFVzK076R+P/eXqsgx5zuuRWukNE=
+k8s.io/api v0.28.2 h1:9mpl5mOb6vXZvqbQmankOfPIGiudghwCoLl1EYfUZbw=
+k8s.io/api v0.28.2/go.mod h1:RVnJBsjU8tcMq7C3iaRSGMeaKt2TWEUXcpIt/90fjEg=
+k8s.io/apimachinery v0.28.2 h1:KCOJLrc6gu+wV1BYgwik4AF4vXOlVJPdiqn0yAWWwXQ=
+k8s.io/apimachinery v0.28.2/go.mod h1:RdzF87y/ngqk9H4z3EL2Rppv5jj95vGS/HaFXrLDApU=
+k8s.io/client-go v0.28.2 h1:DNoYI1vGq0slMBN/SWKMZMw0Rq+0EQW6/AK4v9+3VeY=
+k8s.io/client-go v0.28.2/go.mod h1:sMkApowspLuc7omj1FOSUxSoqjr+d5Q0Yc0LOFnYFJY=
k8s.io/klog/v2 v2.100.1 h1:7WCHKK6K8fNhTqfBhISHQ97KrnJNFZMcQvKp7gP/tmg=
k8s.io/klog/v2 v2.100.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20230816210353-14e408962443 h1:CAIciCnJnSOQxPd0xvpV6JU3D4AJvnYbImPpFpO9Hnw=
diff --git a/pkg/dal/cmd/gen.go b/pkg/dal/cmd/gen.go
index 1ba7bd03..f99ecf72 100644
--- a/pkg/dal/cmd/gen.go
+++ b/pkg/dal/cmd/gen.go
@@ -50,6 +50,7 @@ func main() {
models.WebhookLog{},
models.Builder{},
models.BuilderRunner{},
+ models.WorkQueue{},
)
g.Execute()
diff --git a/pkg/dal/dao/builder.go b/pkg/dal/dao/builder.go
index 5a5658e0..77d77115 100644
--- a/pkg/dal/dao/builder.go
+++ b/pkg/dal/dao/builder.go
@@ -22,6 +22,10 @@ import (
"github.com/go-sigma/sigma/pkg/dal/models"
"github.com/go-sigma/sigma/pkg/dal/query"
+ "github.com/go-sigma/sigma/pkg/types"
+ "github.com/go-sigma/sigma/pkg/types/enums"
+ "github.com/go-sigma/sigma/pkg/utils"
+ "github.com/go-sigma/sigma/pkg/utils/ptr"
)
//go:generate mockgen -destination=mocks/builder.go -package=mocks github.com/go-sigma/sigma/pkg/dal/dao BuilderService
@@ -43,6 +47,8 @@ type BuilderService interface {
CreateRunner(ctx context.Context, log *models.BuilderRunner) error
// GetRunner get runner from object storage or database
GetRunner(ctx context.Context, id int64) (*models.BuilderRunner, error)
+ // ListRunners list builder runners
+ ListRunners(ctx context.Context, id int64, pagination types.Pagination, sort types.Sortable) ([]*models.BuilderRunner, int64, error)
// UpdateRunner update builder runner
UpdateRunner(ctx context.Context, builderID, runnerID int64, updates map[string]interface{}) error
// GetByNextTrigger get by next trigger
@@ -133,6 +139,26 @@ func (s builderService) GetRunner(ctx context.Context, id int64) (*models.Builde
return s.tx.BuilderRunner.WithContext(ctx).Where(s.tx.BuilderRunner.BuilderID.Eq(id)).First()
}
+// ListRunners list builder runners
+func (s builderService) ListRunners(ctx context.Context, id int64, pagination types.Pagination, sort types.Sortable) ([]*models.BuilderRunner, int64, error) {
+ pagination = utils.NormalizePagination(pagination)
+ query := s.tx.BuilderRunner.WithContext(ctx).Where(s.tx.BuilderRunner.BuilderID.Eq(id))
+ field, ok := s.tx.BuilderRunner.GetFieldByName(ptr.To(sort.Sort))
+ if ok {
+ switch ptr.To(sort.Method) {
+ case enums.SortMethodDesc:
+ query = query.Order(field.Desc())
+ case enums.SortMethodAsc:
+ query = query.Order(field)
+ default:
+ query = query.Order(s.tx.BuilderRunner.UpdatedAt.Desc())
+ }
+ } else {
+ query = query.Order(s.tx.BuilderRunner.UpdatedAt.Desc())
+ }
+ return query.FindByPage(ptr.To(pagination.Limit)*(ptr.To(pagination.Page)-1), ptr.To(pagination.Limit))
+}
+
// UpdateRunner update builder runner
func (s builderService) UpdateRunner(ctx context.Context, builderID, runnerID int64, updates map[string]interface{}) error {
matched, err := s.tx.BuilderRunner.WithContext(ctx).Where(s.tx.BuilderRunner.BuilderID.Eq(builderID), s.tx.BuilderRunner.ID.Eq(runnerID)).Updates(updates)
diff --git a/pkg/dal/dao/code_repository.go b/pkg/dal/dao/code_repository.go
index 3a6b79c2..8e3a58b5 100644
--- a/pkg/dal/dao/code_repository.go
+++ b/pkg/dal/dao/code_repository.go
@@ -50,6 +50,8 @@ type CodeRepositoryService interface {
DeleteBranchesInBatches(ctx context.Context, ids []int64) error
// ListAll lists all code repository records in the database
ListAll(ctx context.Context, user3rdPartyID int64) ([]*models.CodeRepository, error)
+ // Get get code repository record by id
+ Get(ctx context.Context, id int64) (*models.CodeRepository, error)
// ListOwnersAll lists all code repository owners records in the database
ListOwnersAll(ctx context.Context, user3rdPartyID int64) ([]*models.CodeRepositoryOwner, error)
// ListWithPagination list code repositories with pagination
@@ -176,6 +178,11 @@ func (s *codeRepositoryService) ListAll(ctx context.Context, user3rdPartyID int6
return s.tx.CodeRepository.WithContext(ctx).Where(s.tx.CodeRepository.User3rdPartyID.Eq(user3rdPartyID)).Find()
}
+// Get get code repository record by id
+func (s *codeRepositoryService) Get(ctx context.Context, id int64) (*models.CodeRepository, error) {
+ return s.tx.CodeRepository.WithContext(ctx).Where(s.tx.CodeRepository.ID.Eq(id)).Preload(s.tx.CodeRepository.User3rdParty).First()
+}
+
// ListOwnersAll lists all code repository owners records in the database
func (s *codeRepositoryService) ListOwnersAll(ctx context.Context, user3rdPartyID int64) ([]*models.CodeRepositoryOwner, error) {
return s.tx.CodeRepositoryOwner.WithContext(ctx).Where(s.tx.CodeRepositoryOwner.User3rdPartyID.Eq(user3rdPartyID)).Find()
diff --git a/pkg/dal/dao/mocks/builder.go b/pkg/dal/dao/mocks/builder.go
index 3eb40324..27ab637e 100644
--- a/pkg/dal/dao/mocks/builder.go
+++ b/pkg/dal/dao/mocks/builder.go
@@ -64,6 +64,21 @@ func (mr *MockBuilderServiceMockRecorder) CreateRunner(arg0, arg1 interface{}) *
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateRunner", reflect.TypeOf((*MockBuilderService)(nil).CreateRunner), arg0, arg1)
}
+// Get mocks base method.
+func (m *MockBuilderService) Get(arg0 context.Context, arg1 int64) (*models.Builder, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Get", arg0, arg1)
+ ret0, _ := ret[0].(*models.Builder)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// Get indicates an expected call of Get.
+func (mr *MockBuilderServiceMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockBuilderService)(nil).Get), arg0, arg1)
+}
+
// GetByNextTrigger mocks base method.
func (m *MockBuilderService) GetByNextTrigger(arg0 context.Context, arg1 time.Time, arg2 int) ([]*models.Builder, error) {
m.ctrl.T.Helper()
@@ -94,6 +109,21 @@ func (mr *MockBuilderServiceMockRecorder) GetByRepositoryID(arg0, arg1 interface
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByRepositoryID", reflect.TypeOf((*MockBuilderService)(nil).GetByRepositoryID), arg0, arg1)
}
+// GetByRepositoryIDs mocks base method.
+func (m *MockBuilderService) GetByRepositoryIDs(arg0 context.Context, arg1 []int64) (map[int64]*models.Builder, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "GetByRepositoryIDs", arg0, arg1)
+ ret0, _ := ret[0].(map[int64]*models.Builder)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// GetByRepositoryIDs indicates an expected call of GetByRepositoryIDs.
+func (mr *MockBuilderServiceMockRecorder) GetByRepositoryIDs(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetByRepositoryIDs", reflect.TypeOf((*MockBuilderService)(nil).GetByRepositoryIDs), arg0, arg1)
+}
+
// GetRunner mocks base method.
func (m *MockBuilderService) GetRunner(arg0 context.Context, arg1 int64) (*models.BuilderRunner, error) {
m.ctrl.T.Helper()
@@ -109,6 +139,20 @@ func (mr *MockBuilderServiceMockRecorder) GetRunner(arg0, arg1 interface{}) *gom
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetRunner", reflect.TypeOf((*MockBuilderService)(nil).GetRunner), arg0, arg1)
}
+// Update mocks base method.
+func (m *MockBuilderService) Update(arg0 context.Context, arg1 int64, arg2 map[string]interface{}) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Update", arg0, arg1, arg2)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Update indicates an expected call of Update.
+func (mr *MockBuilderServiceMockRecorder) Update(arg0, arg1, arg2 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Update", reflect.TypeOf((*MockBuilderService)(nil).Update), arg0, arg1, arg2)
+}
+
// UpdateNextTrigger mocks base method.
func (m *MockBuilderService) UpdateNextTrigger(arg0 context.Context, arg1 int64, arg2 time.Time) error {
m.ctrl.T.Helper()
diff --git a/pkg/dal/dao/mocks/code_repository.go b/pkg/dal/dao/mocks/code_repository.go
index 72b797bc..08a6e858 100644
--- a/pkg/dal/dao/mocks/code_repository.go
+++ b/pkg/dal/dao/mocks/code_repository.go
@@ -121,6 +121,21 @@ func (mr *MockCodeRepositoryServiceMockRecorder) DeleteOwnerInBatches(arg0, arg1
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteOwnerInBatches", reflect.TypeOf((*MockCodeRepositoryService)(nil).DeleteOwnerInBatches), arg0, arg1)
}
+// Get mocks base method.
+func (m *MockCodeRepositoryService) Get(arg0 context.Context, arg1 int64) (*models.CodeRepository, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Get", arg0, arg1)
+ ret0, _ := ret[0].(*models.CodeRepository)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// Get indicates an expected call of Get.
+func (mr *MockCodeRepositoryServiceMockRecorder) Get(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockCodeRepositoryService)(nil).Get), arg0, arg1)
+}
+
// ListAll mocks base method.
func (m *MockCodeRepositoryService) ListAll(arg0 context.Context, arg1 int64) ([]*models.CodeRepository, error) {
m.ctrl.T.Helper()
diff --git a/pkg/dal/dao/mocks/workq.go b/pkg/dal/dao/mocks/workq.go
new file mode 100644
index 00000000..a970c0cd
--- /dev/null
+++ b/pkg/dal/dao/mocks/workq.go
@@ -0,0 +1,80 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/go-sigma/sigma/pkg/dal/dao (interfaces: WorkQueueService)
+
+// Package mocks is a generated GoMock package.
+package mocks
+
+import (
+ context "context"
+ reflect "reflect"
+
+ models "github.com/go-sigma/sigma/pkg/dal/models"
+ enums "github.com/go-sigma/sigma/pkg/types/enums"
+ gomock "go.uber.org/mock/gomock"
+)
+
+// MockWorkQueueService is a mock of WorkQueueService interface.
+type MockWorkQueueService struct {
+ ctrl *gomock.Controller
+ recorder *MockWorkQueueServiceMockRecorder
+}
+
+// MockWorkQueueServiceMockRecorder is the mock recorder for MockWorkQueueService.
+type MockWorkQueueServiceMockRecorder struct {
+ mock *MockWorkQueueService
+}
+
+// NewMockWorkQueueService creates a new mock instance.
+func NewMockWorkQueueService(ctrl *gomock.Controller) *MockWorkQueueService {
+ mock := &MockWorkQueueService{ctrl: ctrl}
+ mock.recorder = &MockWorkQueueServiceMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockWorkQueueService) EXPECT() *MockWorkQueueServiceMockRecorder {
+ return m.recorder
+}
+
+// Create mocks base method.
+func (m *MockWorkQueueService) Create(arg0 context.Context, arg1 *models.WorkQueue) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Create", arg0, arg1)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// Create indicates an expected call of Create.
+func (mr *MockWorkQueueServiceMockRecorder) Create(arg0, arg1 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Create", reflect.TypeOf((*MockWorkQueueService)(nil).Create), arg0, arg1)
+}
+
+// Get mocks base method.
+func (m *MockWorkQueueService) Get(arg0 context.Context) (*models.WorkQueue, error) {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "Get", arg0)
+ ret0, _ := ret[0].(*models.WorkQueue)
+ ret1, _ := ret[1].(error)
+ return ret0, ret1
+}
+
+// Get indicates an expected call of Get.
+func (mr *MockWorkQueueServiceMockRecorder) Get(arg0 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockWorkQueueService)(nil).Get), arg0)
+}
+
+// UpdateStatus mocks base method.
+func (m *MockWorkQueueService) UpdateStatus(arg0 context.Context, arg1 int64, arg2 string, arg3 enums.TaskCommonStatus) error {
+ m.ctrl.T.Helper()
+ ret := m.ctrl.Call(m, "UpdateStatus", arg0, arg1, arg2, arg3)
+ ret0, _ := ret[0].(error)
+ return ret0
+}
+
+// UpdateStatus indicates an expected call of UpdateStatus.
+func (mr *MockWorkQueueServiceMockRecorder) UpdateStatus(arg0, arg1, arg2, arg3 interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateStatus", reflect.TypeOf((*MockWorkQueueService)(nil).UpdateStatus), arg0, arg1, arg2, arg3)
+}
diff --git a/pkg/dal/dao/mocks/workq_factory.go b/pkg/dal/dao/mocks/workq_factory.go
new file mode 100644
index 00000000..3680bed8
--- /dev/null
+++ b/pkg/dal/dao/mocks/workq_factory.go
@@ -0,0 +1,54 @@
+// Code generated by MockGen. DO NOT EDIT.
+// Source: github.com/go-sigma/sigma/pkg/dal/dao (interfaces: WorkQueueServiceFactory)
+
+// Package mocks is a generated GoMock package.
+package mocks
+
+import (
+ reflect "reflect"
+
+ dao "github.com/go-sigma/sigma/pkg/dal/dao"
+ query "github.com/go-sigma/sigma/pkg/dal/query"
+ gomock "go.uber.org/mock/gomock"
+)
+
+// MockWorkQueueServiceFactory is a mock of WorkQueueServiceFactory interface.
+type MockWorkQueueServiceFactory struct {
+ ctrl *gomock.Controller
+ recorder *MockWorkQueueServiceFactoryMockRecorder
+}
+
+// MockWorkQueueServiceFactoryMockRecorder is the mock recorder for MockWorkQueueServiceFactory.
+type MockWorkQueueServiceFactoryMockRecorder struct {
+ mock *MockWorkQueueServiceFactory
+}
+
+// NewMockWorkQueueServiceFactory creates a new mock instance.
+func NewMockWorkQueueServiceFactory(ctrl *gomock.Controller) *MockWorkQueueServiceFactory {
+ mock := &MockWorkQueueServiceFactory{ctrl: ctrl}
+ mock.recorder = &MockWorkQueueServiceFactoryMockRecorder{mock}
+ return mock
+}
+
+// EXPECT returns an object that allows the caller to indicate expected use.
+func (m *MockWorkQueueServiceFactory) EXPECT() *MockWorkQueueServiceFactoryMockRecorder {
+ return m.recorder
+}
+
+// New mocks base method.
+func (m *MockWorkQueueServiceFactory) New(arg0 ...*query.Query) dao.WorkQueueService {
+ m.ctrl.T.Helper()
+ varargs := []interface{}{}
+ for _, a := range arg0 {
+ varargs = append(varargs, a)
+ }
+ ret := m.ctrl.Call(m, "New", varargs...)
+ ret0, _ := ret[0].(dao.WorkQueueService)
+ return ret0
+}
+
+// New indicates an expected call of New.
+func (mr *MockWorkQueueServiceFactoryMockRecorder) New(arg0 ...interface{}) *gomock.Call {
+ mr.mock.ctrl.T.Helper()
+ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "New", reflect.TypeOf((*MockWorkQueueServiceFactory)(nil).New), arg0...)
+}
diff --git a/pkg/dal/dao/workq.go b/pkg/dal/dao/workq.go
new file mode 100644
index 00000000..e47e1800
--- /dev/null
+++ b/pkg/dal/dao/workq.go
@@ -0,0 +1,93 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package dao
+
+import (
+ "context"
+
+ "gorm.io/gorm"
+
+ "github.com/go-sigma/sigma/pkg/dal/models"
+ "github.com/go-sigma/sigma/pkg/dal/query"
+ "github.com/go-sigma/sigma/pkg/types/enums"
+)
+
+//go:generate mockgen -destination=mocks/workq.go -package=mocks github.com/go-sigma/sigma/pkg/dal/dao WorkQueueService
+//go:generate mockgen -destination=mocks/workq_factory.go -package=mocks github.com/go-sigma/sigma/pkg/dal/dao WorkQueueServiceFactory
+
+// WorkQueueService is the interface that provides methods to operate on work queue model
+type WorkQueueService interface {
+ // Create creates a new work queue record in the database
+ Create(ctx context.Context, builder *models.WorkQueue) error
+ // Get get a work queue record
+ Get(ctx context.Context) (*models.WorkQueue, error)
+ // UpdateStatus update a work queue record status
+ UpdateStatus(ctx context.Context, id int64, version, newVersion string, status enums.TaskCommonStatus) error
+}
+
+type workQueueService struct {
+ tx *query.Query
+}
+
+// WorkQueueServiceFactory is the interface that provides the work queue service factory methods.
+type WorkQueueServiceFactory interface {
+ New(txs ...*query.Query) WorkQueueService
+}
+
+type workQueueServiceFactory struct{}
+
+// NewWorkQueueServiceFactory creates a new work queue service factory.
+func NewWorkQueueServiceFactory() WorkQueueServiceFactory {
+ return &workQueueServiceFactory{}
+}
+
+func (f *workQueueServiceFactory) New(txs ...*query.Query) WorkQueueService {
+ tx := query.Q
+ if len(txs) > 0 {
+ tx = txs[0]
+ }
+ return &workQueueService{
+ tx: tx,
+ }
+}
+
+// Create creates a new work queue record in the database
+func (s workQueueService) Create(ctx context.Context, wq *models.WorkQueue) error {
+ return s.tx.WorkQueue.WithContext(ctx).Create(wq)
+}
+
+// Get get a work queue record
+func (s workQueueService) Get(ctx context.Context) (*models.WorkQueue, error) {
+ return s.tx.WorkQueue.WithContext(ctx).Where(s.tx.WorkQueue.Status.Eq(enums.TaskCommonStatusPending)).Order(s.tx.WorkQueue.UpdatedAt).First()
+}
+
+// Update update a work queue record
+func (s workQueueService) UpdateStatus(ctx context.Context, id int64, version, newVersion string, status enums.TaskCommonStatus) error {
+ value := map[string]any{
+ query.WorkQueue.Status.ColumnName().String(): status,
+ query.WorkQueue.Version.ColumnName().String(): newVersion,
+ }
+ result, err := s.tx.WorkQueue.WithContext(ctx).Where(
+ s.tx.WorkQueue.ID.Eq(id),
+ s.tx.WorkQueue.Version.Eq(version),
+ ).UpdateColumns(value)
+ if err != nil {
+ return err
+ }
+ if result.RowsAffected == 0 {
+ return gorm.ErrRecordNotFound
+ }
+ return nil
+}
diff --git a/pkg/dal/migrations/mysql/0001_initialize.up.sql b/pkg/dal/migrations/mysql/0001_initialize.up.sql
index 5303473a..d1999d73 100644
--- a/pkg/dal/migrations/mysql/0001_initialize.up.sql
+++ b/pkg/dal/migrations/mysql/0001_initialize.up.sql
@@ -405,7 +405,9 @@ CREATE TABLE IF NOT EXISTS `work_queue` (
`id` bigint AUTO_INCREMENT PRIMARY KEY,
`topic` varchar(30) NOT NULL,
`payload` BLOB NOT NULL,
+ `times` MEDIUMINT NOT NULL DEFAULT 0,
`version` varchar(30) NOT NULL,
+ `status` ENUM ('Success', 'Failed', 'Pending', 'Doing') NOT NULL DEFAULT 'Pending',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`deleted_at` bigint NOT NULL DEFAULT 0
diff --git a/pkg/dal/migrations/postgresql/0001_initialize.up.sql b/pkg/dal/migrations/postgresql/0001_initialize.up.sql
index 3fbb1de0..1f5fc9dc 100644
--- a/pkg/dal/migrations/postgresql/0001_initialize.up.sql
+++ b/pkg/dal/migrations/postgresql/0001_initialize.up.sql
@@ -474,7 +474,9 @@ CREATE TABLE IF NOT EXISTS "work_queue" (
"id" bigserial PRIMARY KEY,
"topic" varchar(30) NOT NULL,
"payload" bytea NOT NULL,
+ "times" smallint NOT NULL DEFAULT 0,
"version" varchar(30) NOT NULL,
+ "status" daemon_status NOT NULL DEFAULT 'Pending',
"created_at" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updated_at" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
"deleted_at" bigint NOT NULL DEFAULT 0
diff --git a/pkg/dal/migrations/sqlite3/0001_initialize.up.sql b/pkg/dal/migrations/sqlite3/0001_initialize.up.sql
index 530f7523..b3ec90c1 100644
--- a/pkg/dal/migrations/sqlite3/0001_initialize.up.sql
+++ b/pkg/dal/migrations/sqlite3/0001_initialize.up.sql
@@ -403,7 +403,9 @@ CREATE TABLE IF NOT EXISTS `work_queue` (
`id` integer PRIMARY KEY AUTOINCREMENT,
`topic` varchar(30) NOT NULL,
`payload` BLOB NOT NULL,
+ `times` integer NOT NULL DEFAULT 0,
`version` varchar(30) NOT NULL,
+ `status` text CHECK (`status` IN ('Success', 'Failed', 'Pending', 'Scheduling', 'Building')) NOT NULL DEFAULT 'Pending',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`deleted_at` bigint NOT NULL DEFAULT 0
diff --git a/pkg/dal/models/workq.go b/pkg/dal/models/workq.go
new file mode 100644
index 00000000..f8eab60a
--- /dev/null
+++ b/pkg/dal/models/workq.go
@@ -0,0 +1,37 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package models
+
+import (
+ "time"
+
+ "gorm.io/plugin/soft_delete"
+
+ "github.com/go-sigma/sigma/pkg/types/enums"
+)
+
+// WorkQueue ...
+type WorkQueue struct {
+ CreatedAt time.Time
+ UpdatedAt time.Time
+ DeletedAt soft_delete.DeletedAt `gorm:"softDelete:milli"`
+ ID int64 `gorm:"primaryKey"`
+
+ Topic string
+ Payload []byte
+ Times int
+ Version string
+ Status enums.TaskCommonStatus `gorm:"default:Pending"`
+}
diff --git a/pkg/dal/query/gen.go b/pkg/dal/query/gen.go
index bf97281a..f3df83fd 100644
--- a/pkg/dal/query/gen.go
+++ b/pkg/dal/query/gen.go
@@ -39,6 +39,7 @@ var (
UserRecoverCode *userRecoverCode
Webhook *webhook
WebhookLog *webhookLog
+ WorkQueue *workQueue
)
func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
@@ -65,6 +66,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) {
UserRecoverCode = &Q.UserRecoverCode
Webhook = &Q.Webhook
WebhookLog = &Q.WebhookLog
+ WorkQueue = &Q.WorkQueue
}
func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
@@ -92,6 +94,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query {
UserRecoverCode: newUserRecoverCode(db, opts...),
Webhook: newWebhook(db, opts...),
WebhookLog: newWebhookLog(db, opts...),
+ WorkQueue: newWorkQueue(db, opts...),
}
}
@@ -120,6 +123,7 @@ type Query struct {
UserRecoverCode userRecoverCode
Webhook webhook
WebhookLog webhookLog
+ WorkQueue workQueue
}
func (q *Query) Available() bool { return q.db != nil }
@@ -149,6 +153,7 @@ func (q *Query) clone(db *gorm.DB) *Query {
UserRecoverCode: q.UserRecoverCode.clone(db),
Webhook: q.Webhook.clone(db),
WebhookLog: q.WebhookLog.clone(db),
+ WorkQueue: q.WorkQueue.clone(db),
}
}
@@ -185,6 +190,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query {
UserRecoverCode: q.UserRecoverCode.replaceDB(db),
Webhook: q.Webhook.replaceDB(db),
WebhookLog: q.WebhookLog.replaceDB(db),
+ WorkQueue: q.WorkQueue.replaceDB(db),
}
}
@@ -211,6 +217,7 @@ type queryCtx struct {
UserRecoverCode *userRecoverCodeDo
Webhook *webhookDo
WebhookLog *webhookLogDo
+ WorkQueue *workQueueDo
}
func (q *Query) WithContext(ctx context.Context) *queryCtx {
@@ -237,6 +244,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx {
UserRecoverCode: q.UserRecoverCode.WithContext(ctx),
Webhook: q.Webhook.WithContext(ctx),
WebhookLog: q.WebhookLog.WithContext(ctx),
+ WorkQueue: q.WorkQueue.WithContext(ctx),
}
}
diff --git a/pkg/dal/query/work_queues.gen.go b/pkg/dal/query/work_queues.gen.go
new file mode 100644
index 00000000..f84d7519
--- /dev/null
+++ b/pkg/dal/query/work_queues.gen.go
@@ -0,0 +1,357 @@
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+// Code generated by gorm.io/gen. DO NOT EDIT.
+
+package query
+
+import (
+ "context"
+
+ "gorm.io/gorm"
+ "gorm.io/gorm/clause"
+ "gorm.io/gorm/schema"
+
+ "gorm.io/gen"
+ "gorm.io/gen/field"
+
+ "gorm.io/plugin/dbresolver"
+
+ "github.com/go-sigma/sigma/pkg/dal/models"
+)
+
+func newWorkQueue(db *gorm.DB, opts ...gen.DOOption) workQueue {
+ _workQueue := workQueue{}
+
+ _workQueue.workQueueDo.UseDB(db, opts...)
+ _workQueue.workQueueDo.UseModel(&models.WorkQueue{})
+
+ tableName := _workQueue.workQueueDo.TableName()
+ _workQueue.ALL = field.NewAsterisk(tableName)
+ _workQueue.CreatedAt = field.NewTime(tableName, "created_at")
+ _workQueue.UpdatedAt = field.NewTime(tableName, "updated_at")
+ _workQueue.DeletedAt = field.NewUint(tableName, "deleted_at")
+ _workQueue.ID = field.NewInt64(tableName, "id")
+ _workQueue.Topic = field.NewString(tableName, "topic")
+ _workQueue.Payload = field.NewBytes(tableName, "payload")
+ _workQueue.Version = field.NewString(tableName, "version")
+ _workQueue.Status = field.NewField(tableName, "status")
+
+ _workQueue.fillFieldMap()
+
+ return _workQueue
+}
+
+type workQueue struct {
+ workQueueDo workQueueDo
+
+ ALL field.Asterisk
+ CreatedAt field.Time
+ UpdatedAt field.Time
+ DeletedAt field.Uint
+ ID field.Int64
+ Topic field.String
+ Payload field.Bytes
+ Version field.String
+ Status field.Field
+
+ fieldMap map[string]field.Expr
+}
+
+func (w workQueue) Table(newTableName string) *workQueue {
+ w.workQueueDo.UseTable(newTableName)
+ return w.updateTableName(newTableName)
+}
+
+func (w workQueue) As(alias string) *workQueue {
+ w.workQueueDo.DO = *(w.workQueueDo.As(alias).(*gen.DO))
+ return w.updateTableName(alias)
+}
+
+func (w *workQueue) updateTableName(table string) *workQueue {
+ w.ALL = field.NewAsterisk(table)
+ w.CreatedAt = field.NewTime(table, "created_at")
+ w.UpdatedAt = field.NewTime(table, "updated_at")
+ w.DeletedAt = field.NewUint(table, "deleted_at")
+ w.ID = field.NewInt64(table, "id")
+ w.Topic = field.NewString(table, "topic")
+ w.Payload = field.NewBytes(table, "payload")
+ w.Version = field.NewString(table, "version")
+ w.Status = field.NewField(table, "status")
+
+ w.fillFieldMap()
+
+ return w
+}
+
+func (w *workQueue) WithContext(ctx context.Context) *workQueueDo {
+ return w.workQueueDo.WithContext(ctx)
+}
+
+func (w workQueue) TableName() string { return w.workQueueDo.TableName() }
+
+func (w workQueue) Alias() string { return w.workQueueDo.Alias() }
+
+func (w workQueue) Columns(cols ...field.Expr) gen.Columns { return w.workQueueDo.Columns(cols...) }
+
+func (w *workQueue) GetFieldByName(fieldName string) (field.OrderExpr, bool) {
+ _f, ok := w.fieldMap[fieldName]
+ if !ok || _f == nil {
+ return nil, false
+ }
+ _oe, ok := _f.(field.OrderExpr)
+ return _oe, ok
+}
+
+func (w *workQueue) fillFieldMap() {
+ w.fieldMap = make(map[string]field.Expr, 8)
+ w.fieldMap["created_at"] = w.CreatedAt
+ w.fieldMap["updated_at"] = w.UpdatedAt
+ w.fieldMap["deleted_at"] = w.DeletedAt
+ w.fieldMap["id"] = w.ID
+ w.fieldMap["topic"] = w.Topic
+ w.fieldMap["payload"] = w.Payload
+ w.fieldMap["version"] = w.Version
+ w.fieldMap["status"] = w.Status
+}
+
+func (w workQueue) clone(db *gorm.DB) workQueue {
+ w.workQueueDo.ReplaceConnPool(db.Statement.ConnPool)
+ return w
+}
+
+func (w workQueue) replaceDB(db *gorm.DB) workQueue {
+ w.workQueueDo.ReplaceDB(db)
+ return w
+}
+
+type workQueueDo struct{ gen.DO }
+
+func (w workQueueDo) Debug() *workQueueDo {
+ return w.withDO(w.DO.Debug())
+}
+
+func (w workQueueDo) WithContext(ctx context.Context) *workQueueDo {
+ return w.withDO(w.DO.WithContext(ctx))
+}
+
+func (w workQueueDo) ReadDB() *workQueueDo {
+ return w.Clauses(dbresolver.Read)
+}
+
+func (w workQueueDo) WriteDB() *workQueueDo {
+ return w.Clauses(dbresolver.Write)
+}
+
+func (w workQueueDo) Session(config *gorm.Session) *workQueueDo {
+ return w.withDO(w.DO.Session(config))
+}
+
+func (w workQueueDo) Clauses(conds ...clause.Expression) *workQueueDo {
+ return w.withDO(w.DO.Clauses(conds...))
+}
+
+func (w workQueueDo) Returning(value interface{}, columns ...string) *workQueueDo {
+ return w.withDO(w.DO.Returning(value, columns...))
+}
+
+func (w workQueueDo) Not(conds ...gen.Condition) *workQueueDo {
+ return w.withDO(w.DO.Not(conds...))
+}
+
+func (w workQueueDo) Or(conds ...gen.Condition) *workQueueDo {
+ return w.withDO(w.DO.Or(conds...))
+}
+
+func (w workQueueDo) Select(conds ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.Select(conds...))
+}
+
+func (w workQueueDo) Where(conds ...gen.Condition) *workQueueDo {
+ return w.withDO(w.DO.Where(conds...))
+}
+
+func (w workQueueDo) Order(conds ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.Order(conds...))
+}
+
+func (w workQueueDo) Distinct(cols ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.Distinct(cols...))
+}
+
+func (w workQueueDo) Omit(cols ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.Omit(cols...))
+}
+
+func (w workQueueDo) Join(table schema.Tabler, on ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.Join(table, on...))
+}
+
+func (w workQueueDo) LeftJoin(table schema.Tabler, on ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.LeftJoin(table, on...))
+}
+
+func (w workQueueDo) RightJoin(table schema.Tabler, on ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.RightJoin(table, on...))
+}
+
+func (w workQueueDo) Group(cols ...field.Expr) *workQueueDo {
+ return w.withDO(w.DO.Group(cols...))
+}
+
+func (w workQueueDo) Having(conds ...gen.Condition) *workQueueDo {
+ return w.withDO(w.DO.Having(conds...))
+}
+
+func (w workQueueDo) Limit(limit int) *workQueueDo {
+ return w.withDO(w.DO.Limit(limit))
+}
+
+func (w workQueueDo) Offset(offset int) *workQueueDo {
+ return w.withDO(w.DO.Offset(offset))
+}
+
+func (w workQueueDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *workQueueDo {
+ return w.withDO(w.DO.Scopes(funcs...))
+}
+
+func (w workQueueDo) Unscoped() *workQueueDo {
+ return w.withDO(w.DO.Unscoped())
+}
+
+func (w workQueueDo) Create(values ...*models.WorkQueue) error {
+ if len(values) == 0 {
+ return nil
+ }
+ return w.DO.Create(values)
+}
+
+func (w workQueueDo) CreateInBatches(values []*models.WorkQueue, batchSize int) error {
+ return w.DO.CreateInBatches(values, batchSize)
+}
+
+// Save : !!! underlying implementation is different with GORM
+// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values)
+func (w workQueueDo) Save(values ...*models.WorkQueue) error {
+ if len(values) == 0 {
+ return nil
+ }
+ return w.DO.Save(values)
+}
+
+func (w workQueueDo) First() (*models.WorkQueue, error) {
+ if result, err := w.DO.First(); err != nil {
+ return nil, err
+ } else {
+ return result.(*models.WorkQueue), nil
+ }
+}
+
+func (w workQueueDo) Take() (*models.WorkQueue, error) {
+ if result, err := w.DO.Take(); err != nil {
+ return nil, err
+ } else {
+ return result.(*models.WorkQueue), nil
+ }
+}
+
+func (w workQueueDo) Last() (*models.WorkQueue, error) {
+ if result, err := w.DO.Last(); err != nil {
+ return nil, err
+ } else {
+ return result.(*models.WorkQueue), nil
+ }
+}
+
+func (w workQueueDo) Find() ([]*models.WorkQueue, error) {
+ result, err := w.DO.Find()
+ return result.([]*models.WorkQueue), err
+}
+
+func (w workQueueDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.WorkQueue, err error) {
+ buf := make([]*models.WorkQueue, 0, batchSize)
+ err = w.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error {
+ defer func() { results = append(results, buf...) }()
+ return fc(tx, batch)
+ })
+ return results, err
+}
+
+func (w workQueueDo) FindInBatches(result *[]*models.WorkQueue, batchSize int, fc func(tx gen.Dao, batch int) error) error {
+ return w.DO.FindInBatches(result, batchSize, fc)
+}
+
+func (w workQueueDo) Attrs(attrs ...field.AssignExpr) *workQueueDo {
+ return w.withDO(w.DO.Attrs(attrs...))
+}
+
+func (w workQueueDo) Assign(attrs ...field.AssignExpr) *workQueueDo {
+ return w.withDO(w.DO.Assign(attrs...))
+}
+
+func (w workQueueDo) Joins(fields ...field.RelationField) *workQueueDo {
+ for _, _f := range fields {
+ w = *w.withDO(w.DO.Joins(_f))
+ }
+ return &w
+}
+
+func (w workQueueDo) Preload(fields ...field.RelationField) *workQueueDo {
+ for _, _f := range fields {
+ w = *w.withDO(w.DO.Preload(_f))
+ }
+ return &w
+}
+
+func (w workQueueDo) FirstOrInit() (*models.WorkQueue, error) {
+ if result, err := w.DO.FirstOrInit(); err != nil {
+ return nil, err
+ } else {
+ return result.(*models.WorkQueue), nil
+ }
+}
+
+func (w workQueueDo) FirstOrCreate() (*models.WorkQueue, error) {
+ if result, err := w.DO.FirstOrCreate(); err != nil {
+ return nil, err
+ } else {
+ return result.(*models.WorkQueue), nil
+ }
+}
+
+func (w workQueueDo) FindByPage(offset int, limit int) (result []*models.WorkQueue, count int64, err error) {
+ result, err = w.Offset(offset).Limit(limit).Find()
+ if err != nil {
+ return
+ }
+
+ if size := len(result); 0 < limit && 0 < size && size < limit {
+ count = int64(size + offset)
+ return
+ }
+
+ count, err = w.Offset(-1).Limit(-1).Count()
+ return
+}
+
+func (w workQueueDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) {
+ count, err = w.Count()
+ if err != nil {
+ return
+ }
+
+ err = w.Offset(offset).Limit(limit).Scan(result)
+ return
+}
+
+func (w workQueueDo) Scan(result interface{}) (err error) {
+ return w.DO.Scan(result)
+}
+
+func (w workQueueDo) Delete(models ...*models.WorkQueue) (result gen.ResultInfo, err error) {
+ return w.DO.Delete(models)
+}
+
+func (w *workQueueDo) withDO(do gen.Dao) *workQueueDo {
+ w.DO = *do.(*gen.DO)
+ return w
+}
diff --git a/pkg/handlers/apidocs/docs.go b/pkg/handlers/apidocs/docs.go
index a4854025..5091ab3d 100644
--- a/pkg/handlers/apidocs/docs.go
+++ b/pkg/handlers/apidocs/docs.go
@@ -299,6 +299,55 @@ const docTemplate = `{
}
}
},
+ "/coderepos/{provider}/repos/{id}": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "CodeRepository"
+ ],
+ "summary": "Get code repository by id",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "search code repository with provider",
+ "name": "provider",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "code repository id",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/types.CodeRepositoryItem"
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "schema": {
+ "$ref": "#/definitions/xerrors.ErrCode"
+ }
+ }
+ }
+ }
+ },
"/coderepos/{provider}/resync": {
"get": {
"security": [
@@ -3170,6 +3219,7 @@ const docTemplate = `{
],
"properties": {
"buildkit_build_args": {
+ "description": "TODO: validate",
"type": "string",
"example": "a=b,c=d"
},
@@ -3214,6 +3264,7 @@ const docTemplate = `{
"example": "main"
},
"cron_rule": {
+ "description": "TODO: validate",
"type": "string",
"example": "* * * * *"
},
@@ -3290,6 +3341,7 @@ const docTemplate = `{
"example": "{.Ref}"
},
"webhook_tag_tag_template": {
+ "description": "TODO: validate",
"type": "string",
"example": "{.Ref}"
}
@@ -3495,6 +3547,7 @@ const docTemplate = `{
],
"properties": {
"buildkit_build_args": {
+ "description": "TODO: validate",
"type": "string",
"example": "a=b,c=d"
},
@@ -3539,6 +3592,7 @@ const docTemplate = `{
"example": "main"
},
"cron_rule": {
+ "description": "TODO: validate",
"type": "string",
"example": "* * * * *"
},
@@ -3615,6 +3669,7 @@ const docTemplate = `{
"example": "{.Ref}"
},
"webhook_tag_tag_template": {
+ "description": "TODO: validate",
"type": "string",
"example": "{.Ref}"
}
diff --git a/pkg/handlers/apidocs/swagger.json b/pkg/handlers/apidocs/swagger.json
index 288d93db..7a42dfa0 100644
--- a/pkg/handlers/apidocs/swagger.json
+++ b/pkg/handlers/apidocs/swagger.json
@@ -290,6 +290,55 @@
}
}
},
+ "/coderepos/{provider}/repos/{id}": {
+ "get": {
+ "security": [
+ {
+ "BasicAuth": []
+ }
+ ],
+ "consumes": [
+ "application/json"
+ ],
+ "produces": [
+ "application/json"
+ ],
+ "tags": [
+ "CodeRepository"
+ ],
+ "summary": "Get code repository by id",
+ "parameters": [
+ {
+ "type": "string",
+ "description": "search code repository with provider",
+ "name": "provider",
+ "in": "path",
+ "required": true
+ },
+ {
+ "type": "string",
+ "description": "code repository id",
+ "name": "id",
+ "in": "path",
+ "required": true
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "OK",
+ "schema": {
+ "$ref": "#/definitions/types.CodeRepositoryItem"
+ }
+ },
+ "500": {
+ "description": "Internal Server Error",
+ "schema": {
+ "$ref": "#/definitions/xerrors.ErrCode"
+ }
+ }
+ }
+ }
+ },
"/coderepos/{provider}/resync": {
"get": {
"security": [
@@ -3161,6 +3210,7 @@
],
"properties": {
"buildkit_build_args": {
+ "description": "TODO: validate",
"type": "string",
"example": "a=b,c=d"
},
@@ -3205,6 +3255,7 @@
"example": "main"
},
"cron_rule": {
+ "description": "TODO: validate",
"type": "string",
"example": "* * * * *"
},
@@ -3281,6 +3332,7 @@
"example": "{.Ref}"
},
"webhook_tag_tag_template": {
+ "description": "TODO: validate",
"type": "string",
"example": "{.Ref}"
}
@@ -3486,6 +3538,7 @@
],
"properties": {
"buildkit_build_args": {
+ "description": "TODO: validate",
"type": "string",
"example": "a=b,c=d"
},
@@ -3530,6 +3583,7 @@
"example": "main"
},
"cron_rule": {
+ "description": "TODO: validate",
"type": "string",
"example": "* * * * *"
},
@@ -3606,6 +3660,7 @@
"example": "{.Ref}"
},
"webhook_tag_tag_template": {
+ "description": "TODO: validate",
"type": "string",
"example": "{.Ref}"
}
diff --git a/pkg/handlers/apidocs/swagger.yaml b/pkg/handlers/apidocs/swagger.yaml
index bcf6cb15..46bfe606 100644
--- a/pkg/handlers/apidocs/swagger.yaml
+++ b/pkg/handlers/apidocs/swagger.yaml
@@ -516,6 +516,7 @@ definitions:
types.PostBuilderRequestSwagger:
properties:
buildkit_build_args:
+ description: 'TODO: validate'
example: a=b,c=d
type: string
buildkit_context:
@@ -549,6 +550,7 @@ definitions:
example: main
type: string
cron_rule:
+ description: 'TODO: validate'
example: '* * * * *'
type: string
cron_tag_template:
@@ -603,6 +605,7 @@ definitions:
example: '{.Ref}'
type: string
webhook_tag_tag_template:
+ description: 'TODO: validate'
example: '{.Ref}'
type: string
required:
@@ -748,6 +751,7 @@ definitions:
types.PutBuilderRequestSwagger:
properties:
buildkit_build_args:
+ description: 'TODO: validate'
example: a=b,c=d
type: string
buildkit_context:
@@ -781,6 +785,7 @@ definitions:
example: main
type: string
cron_rule:
+ description: 'TODO: validate'
example: '* * * * *'
type: string
cron_tag_template:
@@ -835,6 +840,7 @@ definitions:
example: '{.Ref}'
type: string
webhook_tag_tag_template:
+ description: 'TODO: validate'
example: '{.Ref}'
type: string
required:
@@ -1270,6 +1276,37 @@ paths:
summary: List code repository owners
tags:
- CodeRepository
+ /coderepos/{provider}/repos/{id}:
+ get:
+ consumes:
+ - application/json
+ parameters:
+ - description: search code repository with provider
+ in: path
+ name: provider
+ required: true
+ type: string
+ - description: code repository id
+ in: path
+ name: id
+ required: true
+ type: string
+ produces:
+ - application/json
+ responses:
+ "200":
+ description: OK
+ schema:
+ $ref: '#/definitions/types.CodeRepositoryItem'
+ "500":
+ description: Internal Server Error
+ schema:
+ $ref: '#/definitions/xerrors.ErrCode'
+ security:
+ - BasicAuth: []
+ summary: Get code repository by id
+ tags:
+ - CodeRepository
/coderepos/{provider}/resync:
get:
consumes:
diff --git a/pkg/handlers/builders/builders_get.go b/pkg/handlers/builders/builders_get.go
index c2e47849..dd6290f1 100644
--- a/pkg/handlers/builders/builders_get.go
+++ b/pkg/handlers/builders/builders_get.go
@@ -57,15 +57,15 @@ func (h *handlers) GetBuilder(c echo.Context) error {
builderObj, err := builderService.Get(ctx, req.ID)
if err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
- log.Error().Err(err).Int64("repositoryID", req.ID).Int64("id", req.ID).Msg("Builder not found")
+ log.Error().Err(err).Int64("repositoryID", req.RepositoryID).Int64("id", req.ID).Msg("Builder not found")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeNotFound, fmt.Sprintf("Builder(%d) not found: %s", req.ID, err))
}
- log.Error().Err(err).Int64("repositoryID", req.ID).Int64("id", req.ID).Msg("Get builder failed")
+ log.Error().Err(err).Int64("repositoryID", req.RepositoryID).Int64("id", req.ID).Msg("Get builder failed")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeInternalError, fmt.Sprintf("Builder(%d) not found: %s", req.ID, err))
}
if builderObj.RepositoryID != req.RepositoryID {
- log.Error().Int64("repositoryID", req.ID).Int64("id", req.ID).Msg("Builder not found")
+ log.Error().Int64("repositoryID", req.RepositoryID).Int64("id", req.ID).Msg("Builder not found")
return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeNotFound, fmt.Sprintf("Builder(%d) not found", req.ID))
}
diff --git a/pkg/handlers/builders/builders_runners_list.go b/pkg/handlers/builders/builders_runners_list.go
new file mode 100644
index 00000000..c77f2534
--- /dev/null
+++ b/pkg/handlers/builders/builders_runners_list.go
@@ -0,0 +1,75 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package builders
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+ "strings"
+
+ "github.com/labstack/echo/v4"
+ "github.com/rs/zerolog/log"
+ "gorm.io/gorm"
+
+ "github.com/go-sigma/sigma/pkg/consts"
+ "github.com/go-sigma/sigma/pkg/types"
+ "github.com/go-sigma/sigma/pkg/types/enums"
+ "github.com/go-sigma/sigma/pkg/utils"
+ "github.com/go-sigma/sigma/pkg/xerrors"
+)
+
+// ListRunners handles the list builder runners request
+func (h *handlers) ListRunners(c echo.Context) error {
+ ctx := log.Logger.WithContext(c.Request().Context())
+
+ var req types.ListBuilderRunnersRequest
+ err := utils.BindValidate(c, &req)
+ if err != nil {
+ log.Error().Err(err).Msg("Bind and validate request body failed")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeBadRequest, fmt.Sprintf("Bind and validate request body failed: %v", err))
+ }
+ req.Pagination = utils.NormalizePagination(req.Pagination)
+
+ builderService := h.builderServiceFactory.New()
+ _, err = builderService.GetByRepositoryID(ctx, req.RepositoryID)
+ if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
+ log.Error().Err(err).Int64("id", req.RepositoryID).Msg("Get builder by repository id failed")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeInternalError, fmt.Sprintf("Get builder by repository id failed: %v", err))
+ }
+ runnerObjs, total, err := builderService.ListRunners(ctx, req.ID, req.Pagination, req.Sortable)
+ if err != nil {
+ log.Error().Err(err).Msg("List builder runners failed")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeInternalError, fmt.Sprintf("List builder runners failed: %v", err))
+ }
+ var resp = make([]any, 0, len(runnerObjs))
+ for _, runner := range runnerObjs {
+ platforms := []enums.OciPlatform{}
+ for _, p := range strings.Split(runner.BuildkitPlatforms, ",") {
+ platforms = append(platforms, enums.OciPlatform(p))
+ }
+ resp = append(resp, types.BuilderRunnerItem{
+ ID: runner.ID,
+ BuilderID: runner.BuilderID,
+ Log: runner.Log,
+ Status: runner.Status,
+ Tag: runner.Tag,
+ BuildkitPlatforms: platforms,
+ CreatedAt: runner.CreatedAt.Format(consts.DefaultTimePattern),
+ UpdatedAt: runner.UpdatedAt.Format(consts.DefaultTimePattern),
+ })
+ }
+ return c.JSON(http.StatusOK, types.CommonList{Total: total, Items: resp})
+}
diff --git a/pkg/handlers/builders/handler.go b/pkg/handlers/builders/handler.go
index 3eee3563..1c905e4c 100644
--- a/pkg/handlers/builders/handler.go
+++ b/pkg/handlers/builders/handler.go
@@ -35,6 +35,8 @@ type Handlers interface {
GetBuilder(c echo.Context) error
// PutBuilder handles the put builder request
PutBuilder(c echo.Context) error
+ // ListRunners handles the list builder runners request
+ ListRunners(c echo.Context) error
}
var _ Handlers = &handlers{}
@@ -95,10 +97,11 @@ type factory struct{}
func (f factory) Initialize(e *echo.Echo) error {
builderGroup := e.Group(consts.APIV1+"/repositories/:repository_id/builders", middlewares.AuthWithConfig(middlewares.AuthConfig{}))
- webhookHandler := handlerNew()
- builderGroup.POST("/", webhookHandler.PostBuilder)
- builderGroup.GET("/:id", webhookHandler.GetBuilder)
- builderGroup.PUT("/:id", webhookHandler.PutBuilder)
+ handler := handlerNew()
+ builderGroup.POST("/", handler.PostBuilder)
+ builderGroup.GET("/:id", handler.GetBuilder)
+ builderGroup.PUT("/:id", handler.PutBuilder)
+ builderGroup.GET("/:id/runners/", handler.GetBuilder)
return nil
}
diff --git a/pkg/handlers/coderepos/coderepos_get.go b/pkg/handlers/coderepos/coderepos_get.go
new file mode 100644
index 00000000..0506b01a
--- /dev/null
+++ b/pkg/handlers/coderepos/coderepos_get.go
@@ -0,0 +1,80 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package coderepos
+
+import (
+ "errors"
+ "fmt"
+ "net/http"
+
+ "github.com/labstack/echo/v4"
+ "github.com/rs/zerolog/log"
+ "gorm.io/gorm"
+
+ "github.com/go-sigma/sigma/pkg/consts"
+ "github.com/go-sigma/sigma/pkg/types"
+ "github.com/go-sigma/sigma/pkg/utils"
+ "github.com/go-sigma/sigma/pkg/xerrors"
+)
+
+// Get get code repository by id
+// @Summary Get code repository by id
+// @security BasicAuth
+// @Tags CodeRepository
+// @Accept json
+// @Produce json
+// @Router /coderepos/{provider}/repos/{id} [get]
+// @Param provider path string true "search code repository with provider"
+// @Param id path string true "code repository id"
+// @Success 200 {object} types.CodeRepositoryItem
+// @Failure 500 {object} xerrors.ErrCode
+func (h *handlers) Get(c echo.Context) error {
+ ctx := log.Logger.WithContext(c.Request().Context())
+
+ var req types.GetCodeRepositoryRequest
+ err := utils.BindValidate(c, &req)
+ if err != nil {
+ log.Error().Err(err).Msg("Bind and validate request body failed")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeBadRequest, fmt.Sprintf("Bind and validate request body failed: %v", err))
+ }
+ codeRepositoryService := h.codeRepositoryServiceFactory.New()
+ codeRepositoryObj, err := codeRepositoryService.Get(ctx, req.ID)
+ if err != nil {
+ if errors.Is(err, gorm.ErrRecordNotFound) {
+ log.Error().Err(err).Str("provider", req.Provider.String()).Int64("id", req.ID).Msg("Code repository not found")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeNotFound, fmt.Sprintf("Code repository(%d) not found: %s", req.ID, err))
+ }
+ log.Error().Err(err).Int64("repositoryID", req.ID).Int64("id", req.ID).Msg("Get code repository failed")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeInternalError, fmt.Sprintf("Code repository(%d) not found: %s", req.ID, err))
+ }
+ if codeRepositoryObj.User3rdParty.Provider != req.Provider {
+ log.Error().Err(err).Str("provider", req.Provider.String()).Int64("id", req.ID).Msg("Code repository not found")
+ return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeNotFound, fmt.Sprintf("Code repository(%d) not found", req.ID))
+ }
+
+ return c.JSON(http.StatusOK, types.CodeRepositoryItem{
+ ID: codeRepositoryObj.ID,
+ RepositoryID: codeRepositoryObj.RepositoryID,
+ Name: codeRepositoryObj.Name,
+ OwnerID: codeRepositoryObj.OwnerID,
+ Owner: codeRepositoryObj.Owner,
+ IsOrg: codeRepositoryObj.IsOrg,
+ CloneUrl: codeRepositoryObj.CloneUrl,
+ SshUrl: codeRepositoryObj.SshUrl,
+ OciRepoCount: codeRepositoryObj.OciRepoCount,
+ CreatedAt: codeRepositoryObj.CreatedAt.Format(consts.DefaultTimePattern),
+ UpdatedAt: codeRepositoryObj.UpdatedAt.Format(consts.DefaultTimePattern),
+ })
+}
diff --git a/pkg/handlers/coderepos/handler.go b/pkg/handlers/coderepos/handler.go
index 310051ac..376560f2 100644
--- a/pkg/handlers/coderepos/handler.go
+++ b/pkg/handlers/coderepos/handler.go
@@ -31,6 +31,8 @@ import (
type Handlers interface {
// List list all of the code repositories
List(c echo.Context) error
+ // Get get code repository by id
+ Get(c echo.Context) error
// ListOwner list all of the code repository owner
ListOwners(c echo.Context) error
// ListBranches ...
@@ -111,6 +113,7 @@ func (f factory) Initialize(e *echo.Echo) error {
codeRepositoryHandler := handlerNew()
codereposGroup.GET("/providers", codeRepositoryHandler.Providers)
codereposGroup.GET("/:provider", codeRepositoryHandler.List)
+ codereposGroup.GET("/:provider/repos/:id", codeRepositoryHandler.Get)
codereposGroup.GET("/:provider/user3rdparty", codeRepositoryHandler.User3rdParty)
codereposGroup.GET("/:provider/resync", codeRepositoryHandler.Resync)
codereposGroup.GET("/:provider/owners", codeRepositoryHandler.ListOwners)
diff --git a/pkg/types/builder.go b/pkg/types/builder.go
index 5b9dbffd..96fc17cd 100644
--- a/pkg/types/builder.go
+++ b/pkg/types/builder.go
@@ -153,3 +153,27 @@ type PutBuilderRequest struct {
type PutBuilderRequestSwagger struct {
PostOrPutBuilderRequest
}
+
+// ListBuilderRunnersRequest ...
+type ListBuilderRunnersRequest struct {
+ Pagination
+ Sortable
+
+ ID int64 `json:"id" param:"id" validate:"required,number"`
+ RepositoryID int64 `json:"repository_id" param:"repository_id" example:"10"`
+}
+
+// BuilderRunnerItem ...
+type BuilderRunnerItem struct {
+ ID int64 `json:"id" example:"10"`
+ BuilderID int64
+ Log []byte
+ Status enums.BuildStatus
+
+ Tag string
+ ScmBranch string
+ BuildkitPlatforms []enums.OciPlatform `json:"buildkit_platforms" example:"linux/amd64"`
+
+ CreatedAt string `json:"created_at" example:"2006-01-02 15:04:05"`
+ UpdatedAt string `json:"updated_at" example:"2006-01-02 15:04:05"`
+}
diff --git a/pkg/types/coderepos.go b/pkg/types/coderepos.go
index a4cf4482..ee2e5fd2 100644
--- a/pkg/types/coderepos.go
+++ b/pkg/types/coderepos.go
@@ -51,6 +51,12 @@ type ListCodeRepositoryRequest struct {
Name *string `json:"name,omitempty" query:"name" validate:"omitempty,min=1"`
}
+// GetCodeRepositoryRequest ...
+type GetCodeRepositoryRequest struct {
+ Provider enums.Provider `json:"provider" param:"provider" validate:"required,is_valid_provider"`
+ ID int64 `json:"id" param:"id" validate:"required,number"`
+}
+
// ListCodeRepositoryOwnerRequest ....
type ListCodeRepositoryOwnerRequest struct {
Provider enums.Provider `json:"provider" param:"provider" validate:"required,is_valid_provider"`
diff --git a/pkg/types/enums/enums.go b/pkg/types/enums/enums.go
index a1c60b43..b9cea36d 100644
--- a/pkg/types/enums/enums.go
+++ b/pkg/types/enums/enums.go
@@ -71,6 +71,8 @@ type CacheType string
// CacheKey x ENUM(
// redis,
+// kafka,
+// database,
// )
type WorkQueueType string
diff --git a/pkg/types/enums/enums_enum.go b/pkg/types/enums/enums_enum.go
index 3f45e101..bbe8afc3 100644
--- a/pkg/types/enums/enums_enum.go
+++ b/pkg/types/enums/enums_enum.go
@@ -2003,6 +2003,10 @@ func (x WebhookResourceType) Value() (driver.Value, error) {
const (
// WorkQueueTypeRedis is a WorkQueueType of type redis.
WorkQueueTypeRedis WorkQueueType = "redis"
+ // WorkQueueTypeKafka is a WorkQueueType of type kafka.
+ WorkQueueTypeKafka WorkQueueType = "kafka"
+ // WorkQueueTypeDatabase is a WorkQueueType of type database.
+ WorkQueueTypeDatabase WorkQueueType = "database"
)
var ErrInvalidWorkQueueType = errors.New("not a valid WorkQueueType")
@@ -2020,7 +2024,9 @@ func (x WorkQueueType) IsValid() bool {
}
var _WorkQueueTypeValue = map[string]WorkQueueType{
- "redis": WorkQueueTypeRedis,
+ "redis": WorkQueueTypeRedis,
+ "kafka": WorkQueueTypeKafka,
+ "database": WorkQueueTypeDatabase,
}
// ParseWorkQueueType attempts to convert a string to a WorkQueueType.
diff --git a/pkg/workq/database/consumer.go b/pkg/workq/database/consumer.go
new file mode 100644
index 00000000..f58a7783
--- /dev/null
+++ b/pkg/workq/database/consumer.go
@@ -0,0 +1,95 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package database
+
+import (
+ "context"
+ "path"
+ "reflect"
+
+ "github.com/google/uuid"
+ "github.com/rs/zerolog/log"
+
+ "github.com/go-sigma/sigma/pkg/configs"
+ "github.com/go-sigma/sigma/pkg/dal/dao"
+ "github.com/go-sigma/sigma/pkg/types/enums"
+ "github.com/go-sigma/sigma/pkg/workq"
+)
+
+func init() {
+ workq.ConsumerClientFactories[path.Base(reflect.TypeOf(consumerFactory{}).PkgPath())] = &consumerFactory{}
+}
+
+type consumerFactory struct{}
+
+// NewWorkQueueConsumer ...
+func (f consumerFactory) New(_ configs.Configuration) error {
+ for topic, c := range workq.TopicConsumers {
+ go func(consumer workq.Consumer, topic string) {
+ handler := &consumerHandler{
+ processingSemaphore: make(chan struct{}, consumer.Concurrency),
+ consumer: consumer,
+ }
+ handler.Consume(topic)
+ }(c, topic)
+ }
+ return nil
+}
+
+type consumerHandler struct {
+ processingSemaphore chan struct{}
+ consumer workq.Consumer
+}
+
+func (h *consumerHandler) Consume(topic string) {
+ for {
+ err := h.consume()
+ if err != nil {
+ log.Error().Err(err).Msg("Consume topic failed")
+ }
+ }
+}
+
+func (h *consumerHandler) consume() error {
+ h.processingSemaphore <- struct{}{}
+ defer func() {
+ <-h.processingSemaphore
+ }()
+ workQueueService := dao.NewWorkQueueServiceFactory().New()
+ daoCtx := log.Logger.WithContext(context.Background())
+ wq, err := workQueueService.Get(daoCtx)
+ if err != nil {
+ return err
+ }
+ newVersion := uuid.New().String()
+ err = workQueueService.UpdateStatus(daoCtx, wq.ID, wq.Version, newVersion, enums.TaskCommonStatusDoing)
+ if err != nil {
+ return err
+ }
+ ctx := context.Background()
+ if h.consumer.Timeout != 0 {
+ var ctxCancel context.CancelFunc
+ ctx, ctxCancel = context.WithTimeout(ctx, h.consumer.Timeout)
+ defer ctxCancel()
+ }
+ err = h.consumer.Handler(ctx, wq.Payload)
+ if err != nil {
+ wq.Times++
+ if wq.Times < h.consumer.MaxRetry {
+ return workQueueService.UpdateStatus(daoCtx, wq.ID, newVersion, uuid.New().String(), enums.TaskCommonStatusPending)
+ }
+ }
+ return nil
+}
diff --git a/pkg/workq/database/producer.go b/pkg/workq/database/producer.go
new file mode 100644
index 00000000..dcae1ed5
--- /dev/null
+++ b/pkg/workq/database/producer.go
@@ -0,0 +1,58 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package database
+
+import (
+ "context"
+ "path"
+ "reflect"
+
+ "github.com/google/uuid"
+
+ "github.com/go-sigma/sigma/pkg/configs"
+ "github.com/go-sigma/sigma/pkg/dal/dao"
+ "github.com/go-sigma/sigma/pkg/dal/models"
+ "github.com/go-sigma/sigma/pkg/utils"
+ "github.com/go-sigma/sigma/pkg/workq"
+)
+
+func init() {
+ workq.ProducerClientFactories[path.Base(reflect.TypeOf(producerFactory{}).PkgPath())] = &producerFactory{}
+}
+
+type producer struct {
+ workQueueServiceFactory dao.WorkQueueServiceFactory
+}
+
+type producerFactory struct{}
+
+// NewWorkQueueProducer ...
+func (f producerFactory) New(_ configs.Configuration) (workq.WorkQueueProducer, error) {
+ p := &producer{
+ workQueueServiceFactory: dao.NewWorkQueueServiceFactory(),
+ }
+ return p, nil
+}
+
+// Produce ...
+func (p *producer) Produce(ctx context.Context, topic string, payload any) error {
+ wq := &models.WorkQueue{
+ Topic: topic,
+ Payload: utils.MustMarshal(payload),
+ Version: uuid.New().String(),
+ }
+ workQueueService := p.workQueueServiceFactory.New()
+ return workQueueService.Create(ctx, wq)
+}
diff --git a/pkg/workq/kafka/config.go b/pkg/workq/kafka/config.go
new file mode 100644
index 00000000..787d05ab
--- /dev/null
+++ b/pkg/workq/kafka/config.go
@@ -0,0 +1,34 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kafka
+
+import (
+ "time"
+
+ "github.com/IBM/sarama"
+
+ "github.com/go-sigma/sigma/pkg/configs"
+)
+
+// Config ...
+func Config(cfg configs.Configuration) *sarama.Config {
+ config := sarama.NewConfig()
+ config.Producer.Return.Successes = true
+ config.Producer.RequiredAcks = sarama.WaitForAll
+ config.Producer.Retry.Max = 5
+ config.Consumer.Group.Session.Timeout = 10 * time.Second
+ config.Consumer.Group.Heartbeat.Interval = 3 * time.Second
+ return config
+}
diff --git a/pkg/workq/kafka/consumer.go b/pkg/workq/kafka/consumer.go
new file mode 100644
index 00000000..a07744cf
--- /dev/null
+++ b/pkg/workq/kafka/consumer.go
@@ -0,0 +1,148 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kafka
+
+import (
+ "context"
+ "encoding/json"
+ "fmt"
+ "path"
+ "reflect"
+ "time"
+
+ "github.com/IBM/sarama"
+ "github.com/rs/zerolog/log"
+
+ "github.com/go-sigma/sigma/pkg/configs"
+ "github.com/go-sigma/sigma/pkg/consts"
+ "github.com/go-sigma/sigma/pkg/utils"
+ "github.com/go-sigma/sigma/pkg/workq"
+)
+
+// ConsumerGroupHandler ...
+type ConsumerGroupHandler struct {
+ processingSemaphore chan struct{}
+ consumer workq.Consumer
+ producer sarama.SyncProducer
+}
+
+// Setup ...
+func (h *ConsumerGroupHandler) Setup(session sarama.ConsumerGroupSession) error {
+ return nil
+}
+
+// Cleanup ...
+func (h *ConsumerGroupHandler) Cleanup(session sarama.ConsumerGroupSession) error {
+ return nil
+}
+
+// ConsumeClaim ...
+func (h *ConsumerGroupHandler) ConsumeClaim(session sarama.ConsumerGroupSession, claim sarama.ConsumerGroupClaim) error {
+ for {
+ h.processingSemaphore <- struct{}{}
+ select {
+ case message := <-claim.Messages():
+ go func() {
+ defer func() {
+ <-h.processingSemaphore
+ }()
+ var msg MessageWrapper
+ err := json.Unmarshal(message.Value, &msg)
+ if err != nil {
+ log.Error().Err(err).Str("message", string(message.Value)).Msg("Unmarshal message failed")
+ return
+ }
+ ctx := session.Context()
+ if h.consumer.Timeout != 0 {
+ var ctxCancel context.CancelFunc
+ ctx, ctxCancel = context.WithTimeout(session.Context(), h.consumer.Timeout)
+ defer ctxCancel()
+ }
+ err = h.consumer.Handler(ctx, message.Value)
+ if err != nil {
+ msg.Times++
+ if msg.Times < h.consumer.MaxRetry {
+ _, _, err := h.producer.SendMessage(&sarama.ProducerMessage{
+ Topic: message.Topic,
+ Value: sarama.ByteEncoder(utils.MustMarshal(msg)),
+ })
+ if err != nil {
+ log.Error().Err(err).Str("topic", message.Topic).Str("payload", string(utils.MustMarshal(msg))).Msg("Resend message failed")
+ return
+ }
+ }
+ }
+ }()
+ case <-session.Context().Done():
+ return nil
+ }
+ }
+}
+
+// MessageWrapper ...
+type MessageWrapper struct {
+ Times int
+ Payload []byte
+}
+
+func init() {
+ workq.ConsumerClientFactories[path.Base(reflect.TypeOf(consumerFactory{}).PkgPath())] = &consumerFactory{}
+}
+
+type consumerFactory struct{}
+
+// NewWorkQueueConsumer ...
+func (f consumerFactory) New(_ configs.Configuration) error {
+ config := sarama.NewConfig()
+ config.Producer.Return.Successes = true
+ config.Producer.RequiredAcks = sarama.WaitForAll
+ config.Producer.Retry.Max = 5
+ config.Consumer.Group.Session.Timeout = 10 * time.Second
+ config.Consumer.Group.Heartbeat.Interval = 3 * time.Second
+ config.Consumer.Group.Rebalance.Strategy = sarama.NewBalanceStrategyRoundRobin()
+
+ client, err := sarama.NewClient([]string{}, config)
+ if err != nil {
+ return err
+ }
+
+ producer, err := sarama.NewSyncProducerFromClient(client)
+ if err != nil {
+ log.Error().Err(err).Msg("Create producer failed")
+ }
+
+ for topic, c := range workq.TopicConsumers {
+ consumerGroup, err := sarama.NewConsumerGroupFromClient(fmt.Sprintf("%s-%s", consts.AppName, topic), client)
+ if err != nil {
+ return err
+ }
+ go func(consumer workq.Consumer, topic string) {
+ for {
+ handler := &ConsumerGroupHandler{
+ processingSemaphore: make(chan struct{}, consumer.Concurrency),
+ consumer: consumer,
+ producer: producer,
+ }
+ err := consumerGroup.Consume(context.Background(), []string{topic}, handler)
+ if err != nil {
+ log.Error().Err(err).Str("topic", topic).Msg("Consume topics failed")
+ return
+ }
+ }
+ }(c, topic)
+ }
+
+ return nil
+}
diff --git a/pkg/workq/kafka/producer.go b/pkg/workq/kafka/producer.go
new file mode 100644
index 00000000..2dfa8952
--- /dev/null
+++ b/pkg/workq/kafka/producer.go
@@ -0,0 +1,71 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package kafka
+
+import (
+ "context"
+ "path"
+ "reflect"
+
+ "github.com/IBM/sarama"
+ "github.com/rs/zerolog/log"
+
+ "github.com/go-sigma/sigma/pkg/configs"
+ "github.com/go-sigma/sigma/pkg/utils"
+ "github.com/go-sigma/sigma/pkg/workq"
+)
+
+func init() {
+ workq.ProducerClientFactories[path.Base(reflect.TypeOf(producerFactory{}).PkgPath())] = &producerFactory{}
+}
+
+type producerFactory struct{}
+
+// NewWorkQueueProducer ...
+func (f producerFactory) New(_ configs.Configuration) (workq.WorkQueueProducer, error) {
+ config := sarama.NewConfig()
+ config.Producer.Return.Successes = true
+ config.Producer.RequiredAcks = sarama.WaitForAll
+ config.Producer.Retry.Max = 5
+ client, err := sarama.NewClient([]string{}, config)
+ if err != nil {
+ return nil, err
+ }
+
+ p, err := sarama.NewSyncProducerFromClient(client)
+ if err != nil {
+ log.Error().Err(err).Msg("Create producer failed")
+ return nil, err
+ }
+ return &producer{
+ producer: p,
+ }, nil
+}
+
+type producer struct {
+ producer sarama.SyncProducer
+}
+
+func (p *producer) Produce(_ context.Context, topic string, payload any) error {
+ message := MessageWrapper{
+ Times: 0,
+ Payload: utils.MustMarshal(payload),
+ }
+ _, _, err := p.producer.SendMessage(&sarama.ProducerMessage{
+ Topic: topic,
+ Value: sarama.ByteEncoder(utils.MustMarshal(message)),
+ })
+ return err
+}
diff --git a/pkg/workq/workq.go b/pkg/workq/workq.go
new file mode 100644
index 00000000..a7a613ec
--- /dev/null
+++ b/pkg/workq/workq.go
@@ -0,0 +1,92 @@
+// Copyright 2023 sigma
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package workq
+
+import (
+ "context"
+ "fmt"
+ "strings"
+ "time"
+
+ "github.com/go-sigma/sigma/pkg/configs"
+)
+
+// Message ...
+type Message struct {
+ Topic string
+ Payload []byte
+}
+
+type Consumer struct {
+ Handler func(ctx context.Context, payload []byte) error
+ Concurrency int
+ MaxRetry int
+ Timeout time.Duration
+}
+
+var TopicConsumers = make(map[string]Consumer)
+
+// WorkQueueProducer ...
+type WorkQueueProducer interface {
+ // Produce ...
+ Produce(ctx context.Context, topic string, payload any) error
+}
+
+// WorkQueueConsumer ...
+type WorkQueueConsumer interface {
+ // Consume ...
+ Run(ctx context.Context)
+}
+
+// ConsumerClientFactory ...
+type ConsumerClientFactory interface {
+ New(config configs.Configuration) error
+}
+
+// ProducerClientFactory ...
+type ProducerClientFactory interface {
+ New(config configs.Configuration) (WorkQueueProducer, error)
+}
+
+// ConsumerClientFactories ...
+var ConsumerClientFactories = make(map[string]ConsumerClientFactory, 5)
+
+// ProducerClientFactories ...
+var ProducerClientFactories = make(map[string]ProducerClientFactory, 5)
+
+// Initialize ...
+func Initialize(config configs.Configuration) error {
+ consumerClientFactory, ok := ConsumerClientFactories[strings.ToLower(config.WorkQueue.Type.String())]
+ if !ok {
+ return fmt.Errorf("Work queue consumer(%s) not support", config.WorkQueue.Type.String())
+ }
+ err := consumerClientFactory.New(config)
+ if err != nil {
+ return err
+ }
+ producerClientFactory, ok := ProducerClientFactories[strings.ToLower(config.WorkQueue.Type.String())]
+ if !ok {
+ return fmt.Errorf("Work queue producer(%s) not support", config.WorkQueue.Type.String())
+ }
+ producer, err := producerClientFactory.New(config)
+ if err != nil {
+ return err
+ }
+ ProducerClient = producer
+ return nil
+}
+
+// ProducerClient ...
+var ProducerClient WorkQueueProducer
diff --git a/web/src/App.tsx b/web/src/App.tsx
index c1a9c074..0f89953c 100644
--- a/web/src/App.tsx
+++ b/web/src/App.tsx
@@ -30,6 +30,7 @@ import NamespaceDaemonTasks from "./pages/Namespace/DaemonTask";
import CodeRepositoryHome from './pages/CodeRepository';
import CodeRepositoryList from './pages/CodeRepository/List';
+import BuilderRunner from './pages/CodeRepository/BuilderRunner';
import BuildersSetup from './pages/Builder/Setup';
@@ -70,6 +71,7 @@ export default function App() {