From 8c2e25ba3dd46b81099147ac58ade28c12511213 Mon Sep 17 00:00:00 2001 From: Tosone Date: Fri, 1 Sep 2023 00:20:20 +0800 Subject: [PATCH] :sparkles: Builder setup page (#189) * :sparkles: Resync code repo response 202 * :sparkles: Sync branches * :sparkles: Builder setup page --- go.mod | 12 +- go.sum | 85 +- pkg/daemon/coderepo/coderepo.go | 4 + pkg/daemon/coderepo/diff.go | 80 +- pkg/daemon/coderepo/gitea.go | 2 +- pkg/daemon/coderepo/github.go | 46 +- pkg/daemon/coderepo/gitlab.go | 27 +- pkg/dal/cmd/gen.go | 1 + pkg/dal/dao/code_repository.go | 28 + pkg/dal/dao/mocks/code_repository.go | 44 ++ .../migrations/mysql/0001_initialize.up.sql | 11 + .../postgresql/0001_initialize.up.sql | 11 + .../migrations/sqlite3/0001_initialize.up.sql | 15 +- pkg/dal/models/code_repository.go | 12 + pkg/dal/query/code_repositories.gen.go | 83 +- pkg/dal/query/code_repository_branches.gen.go | 351 +++++++++ pkg/dal/query/gen.go | 8 + pkg/dal/query/user_3rdparty.gen.go | 1 + pkg/handlers/apidocs/docs.go | 193 ++++- pkg/handlers/apidocs/swagger.json | 193 ++++- pkg/handlers/apidocs/swagger.yaml | 123 ++- pkg/handlers/coderepos/coderepos_branches.go | 53 ++ pkg/handlers/coderepos/coderepos_resync.go | 12 +- .../coderepos/coderepos_user3rdparty.go | 9 + pkg/handlers/coderepos/handler.go | 3 + pkg/handlers/distribution/base/tags_list.go | 2 +- .../distribution/upload/upload_put.go | 2 +- pkg/handlers/validators/reference_get.go | 2 +- pkg/types/coderepos.go | 13 + pkg/types/user.go | 2 +- pkg/utils/imagerefs/reference.go | 2 +- pkg/validators/validators.go | 2 +- web/package.json | 4 +- web/src/App.tsx | 9 +- web/src/components/Menu/index.tsx | 3 +- web/src/interfaces/index.ts | 14 +- web/src/pages/Builder/Setup.tsx | 731 ++++++++++++++++++ web/src/pages/CodeRepository/List.tsx | 23 +- web/src/pages/CodeRepository/index.tsx | 2 +- web/yarn.lock | 16 +- 40 files changed, 2162 insertions(+), 72 deletions(-) create mode 100644 pkg/dal/query/code_repository_branches.gen.go create mode 100644 pkg/handlers/coderepos/coderepos_branches.go create mode 100644 web/src/pages/Builder/Setup.tsx diff --git a/go.mod b/go.mod index 3f6730a0..bdb16045 100644 --- a/go.mod +++ b/go.mod @@ -10,13 +10,13 @@ require ( github.com/aliyun/aliyun-oss-go-sdk v2.2.9+incompatible github.com/anchore/syft v0.88.0 github.com/aquasecurity/trivy v0.44.1 - github.com/aws/aws-sdk-go v1.44.332 + github.com/aws/aws-sdk-go v1.45.0 github.com/bytedance/sonic v1.10.0 github.com/caarlos0/env/v9 v9.0.0 github.com/casbin/casbin/v2 v2.77.1 github.com/casbin/gorm-adapter/v3 v3.18.1 github.com/deckarep/golang-set/v2 v2.3.1 - github.com/distribution/distribution/v3 v3.0.0-20230824182353-293b588075cb + github.com/distribution/distribution/v3 v3.0.0-20230831143946-2e50e6d2e6da github.com/docker/cli v24.0.5+incompatible github.com/docker/docker v24.0.5+incompatible github.com/dustin/go-humanize v1.0.1 @@ -24,7 +24,7 @@ require ( github.com/glebarez/sqlite v1.9.0 github.com/go-git/go-git/v5 v5.8.1 github.com/go-playground/validator v9.31.0+incompatible - github.com/go-redsync/redsync/v4 v4.8.1 + github.com/go-redsync/redsync/v4 v4.8.2 github.com/go-resty/resty/v2 v2.7.0 github.com/golang-jwt/jwt/v5 v5.0.0 github.com/golang-migrate/migrate/v4 v4.16.2 @@ -47,8 +47,8 @@ require ( github.com/spf13/cobra v1.7.0 github.com/spf13/viper v1.16.0 github.com/stretchr/testify v1.8.4 - github.com/swaggo/echo-swagger v1.4.0 - github.com/swaggo/swag v1.16.1 + github.com/swaggo/echo-swagger v1.4.1 + github.com/swaggo/swag v1.16.2 github.com/tencentyun/cos-go-sdk-v5 v0.7.42 github.com/tidwall/gjson v1.16.0 github.com/wagslane/go-password-validator v0.3.0 @@ -95,6 +95,7 @@ require ( github.com/containerd/stargz-snapshotter/estargz v0.14.3 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/docker/distribution v2.8.2+incompatible // indirect github.com/docker/docker-credential-helpers v0.8.0 // indirect github.com/docker/go-connections v0.4.0 // indirect @@ -104,6 +105,7 @@ require ( github.com/facebookincubator/nvdtools v0.1.5 // 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 github.com/github/go-spdx/v2 v2.1.2 // indirect github.com/glebarez/go-sqlite v1.21.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect diff --git a/go.sum b/go.sum index cda12d90..e6fd32c9 100644 --- a/go.sum +++ b/go.sum @@ -122,8 +122,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.44.332 h1:Ze+98F41+LxoJUdsisAFThV+0yYYLYw17/Vt0++nFYM= -github.com/aws/aws-sdk-go v1.44.332/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= +github.com/aws/aws-sdk-go v1.45.0 h1:qoVOQHuLacxJMO71T49KeE70zm+Tk3vtrl7XO4VUPZc= +github.com/aws/aws-sdk-go v1.45.0/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= @@ -206,8 +206,10 @@ 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-20230824182353-293b588075cb h1:ocxWObSQfbsmMkyEcE/tphHQU4D7yGQz5xR6AIZ16Tc= -github.com/distribution/distribution/v3 v3.0.0-20230824182353-293b588075cb/go.mod h1:WREzLx07iIFUGvbm6tBoqGt40zOC3whiM1qkcWOMFrs= +github.com/distribution/distribution/v3 v3.0.0-20230831143946-2e50e6d2e6da h1:5liR3AT8mlPdQXUCtepIxURCYVElS6Qa/CfySAi0zgA= +github.com/distribution/distribution/v3 v3.0.0-20230831143946-2e50e6d2e6da/go.mod h1:6HaGL2UUpiM1lzBNxOyohyrXWkZWzf/UVN90NV2B79o= +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= github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v24.0.5+incompatible h1:WeBimjvS0eKdH4Ygx+ihVq1Q++xg36M/rMi4aXAvodc= @@ -258,6 +260,7 @@ github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4 github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= +github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/github/go-spdx/v2 v2.1.2 h1:p+Tv0yMgcuO0/vnMe9Qh4tmUgYhI6AsLVlakZ/Sx+DM= github.com/github/go-spdx/v2 v2.1.2/go.mod h1:hMCrsFgT0QnCwn7G8gxy/MxMpy67WgZrwFeISTn0o6w= @@ -282,8 +285,11 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= @@ -314,8 +320,8 @@ github.com/go-redis/redis/v7 v7.4.0 h1:7obg6wUoj05T0EpY0o8B59S9w5yeMWql7sw2kwNW1 github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= github.com/go-redis/redis/v8 v8.11.4/go.mod h1:2Z2wHZXdQpCDXEGzqMockDpNyYvi2l4Pxt6RJr792+w= github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= -github.com/go-redsync/redsync/v4 v4.8.1 h1:rq2RvdTI0obznMdxKUWGdmmulo7lS9yCzb8fgDKOlbM= -github.com/go-redsync/redsync/v4 v4.8.1/go.mod h1:LmUAsQuQxhzZAoGY7JS6+dNhNmZyonMZiiEDY9plotM= +github.com/go-redsync/redsync/v4 v4.8.2 h1:/b+jidlwOnSOl605hmNsd+ohfr/qB1EpLiKnCYkiw28= +github.com/go-redsync/redsync/v4 v4.8.2/go.mod h1:83QPGYHk0Wt2LhFo3n9xCrUGPQrQvejVTVR08KX032g= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -382,8 +388,8 @@ github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= -github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= -github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= +github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws= +github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= @@ -400,6 +406,7 @@ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-containerregistry v0.16.1 h1:rUEt426sR6nyrL3gt+18ibRcvYpKYdpsa5ZW7MA08dQ= @@ -428,6 +435,7 @@ github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLe github.com/google/pprof v0.0.0-20201218002935-b9804c9f04c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= +github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= @@ -731,16 +739,34 @@ github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9l github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/oklog/ulid/v2 v2.1.0/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc= github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= +github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= +github.com/onsi/ginkgo/v2 v2.1.4/go.mod h1:um6tUpWM/cxCK3/FK8BXqEiUMUwRgSM4JXG47RKZmLU= +github.com/onsi/ginkgo/v2 v2.1.6/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk= +github.com/onsi/ginkgo/v2 v2.3.0/go.mod h1:Eew0uilEqZmIEZr8JrvYlvOM7Rr6xzTmMV8AyFNU9d0= +github.com/onsi/ginkgo/v2 v2.4.0/go.mod h1:iHkDK1fKGcBoEHT5W7YBq4RFWaQulw+caOMkAt4OrFo= +github.com/onsi/ginkgo/v2 v2.5.0/go.mod h1:Luc4sArBICYCS8THh8v3i3i5CuSZO+RaQRaJoeNwomw= +github.com/onsi/ginkgo/v2 v2.7.0/go.mod h1:yjiuMwPokqY1XauOgju45q3sJt6VzQ/Fict1LFVcsAo= +github.com/onsi/ginkgo/v2 v2.8.0/go.mod h1:6JsQiECmxCa3V5st74AL/AmsV482EDdVrGaVW6z3oYU= github.com/onsi/ginkgo/v2 v2.9.4 h1:xR7vG4IXt5RWx6FfIjyAtsoMAtnc3C/rFXBBd2AjZwE= github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro= +github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo= +github.com/onsi/gomega v1.21.1/go.mod h1:iYAIXgPSaDHak0LCMA+AWBpIKBr8WZicMxnE8luStNc= +github.com/onsi/gomega v1.22.1/go.mod h1:x6n7VNe4hw0vkyYUM4mjIXx3JbLiPaBPNgB7PRQ1tuM= +github.com/onsi/gomega v1.24.0/go.mod h1:Z/NWtiqwBrwUt4/2loMmHL63EDLnYHmVbuBpDr2vQAg= +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/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= @@ -750,6 +776,7 @@ github.com/opencontainers/image-spec v1.1.0-rc4 h1:oOxKUJWnFC4YGHCCMNql1x4YaDfYB github.com/opencontainers/image-spec v1.1.0-rc4/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/getopt v0.0.0-20170112200414-7148bc3a4c30/go.mod h1:85jBQOZwpVEaDAr341tbn15RS4fCAsIst0qp7i8ex1o= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= @@ -803,6 +830,8 @@ github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OK github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= github.com/rs/zerolog v1.30.0 h1:SymVODrcRsaRaSInD9yQtKbtWqwsfoPcRff/oRXLj4c= github.com/rs/zerolog v1.30.0/go.mod h1:/tk+P47gFdPXq4QYjvCmT5/Gsug2nagsFWBWhAiSi1w= +github.com/rueian/rueidis v0.0.93 h1:cG905akj2+QyHx0x9y4mN0K8vLi6M94QiyoLulXS3l0= +github.com/rueian/rueidis v0.0.93/go.mod h1:lo6LBci0D986usi5Wxjb4RVNaWENKYbHZSnufGJ9bTE= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= @@ -879,12 +908,12 @@ github.com/stvp/tempredis v0.0.0-20181119212430-b82af8480203/go.mod h1:oqN97ltKN github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/swaggo/echo-swagger v1.4.0 h1:RCxLKySw1SceHLqnmc41pKyiIeE+OiD7NSI7FUOBlLo= -github.com/swaggo/echo-swagger v1.4.0/go.mod h1:Wh3VlwjZGZf/LH0s81tz916JokuPG7y/ZqaqnckYqoQ= +github.com/swaggo/echo-swagger v1.4.1 h1:Yf0uPaJWp1uRtDloZALyLnvdBeoEL5Kc7DtnjzO/TUk= +github.com/swaggo/echo-swagger v1.4.1/go.mod h1:C8bSi+9yH2FLZsnhqMZLIZddpUxZdBYuNHbtaS1Hljc= github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw= github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM= -github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg= -github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto= +github.com/swaggo/swag v1.16.2 h1:28Pp+8DkQoV+HLzLx8RGJZXNGKbFqnuvSbAAtoxiY04= +github.com/swaggo/swag v1.16.2/go.mod h1:6YzXnDcpr0767iOejs318CwYkCQqyGer6BizOg03f+E= github.com/sylabs/sif/v2 v2.12.0 h1:mghM4elFasymxIWYZ8q/eLnDRMOOhRrrKLrEceVQm08= github.com/sylabs/sif/v2 v2.12.0/go.mod h1:Gn6bQvH4q4CH2h8BR9Qkuc1LvhYsfhOxCU7U6gS8jto= github.com/sylabs/squashfs v0.6.1 h1:4hgvHnD9JGlYWwT0bPYNt9zaz23mAV3Js+VEgQoRGYQ= @@ -938,6 +967,7 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= @@ -954,6 +984,11 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= +go.opentelemetry.io/otel v1.12.0/go.mod h1:geaoz0L0r1BEOR81k7/n9W4TCXYCJ7bPO7K374jQHG0= +go.opentelemetry.io/otel/metric v0.35.0/go.mod h1:qAcbhaTRFU6uG8QM7dDo7XvFsWcugziq/5YI065TokQ= +go.opentelemetry.io/otel/sdk v1.12.0/go.mod h1:WYcvtgquYvgODEvxOry5owO2y9MyciW7JqMz6cpXShE= +go.opentelemetry.io/otel/sdk/metric v0.35.0/go.mod h1:eDyp1GxSiwV98kr7w4pzrszQh/eze9MqBqPd2bCPmyE= +go.opentelemetry.io/otel/trace v1.12.0/go.mod h1:pHlgBynn6s25qJ2szD+Bv+iwKJttjHSI3lUAyf0GNuQ= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -962,8 +997,9 @@ go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= -go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= 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/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= @@ -995,6 +1031,7 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= @@ -1040,7 +1077,10 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= +golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.6.0/go.mod h1:4mET923SAdbXp2ki8ey+zGs1SLqsuM2Y0uvdZR/fUNI= +golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= @@ -1090,11 +1130,16 @@ golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= @@ -1212,18 +1257,23 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220919091848-fb04ddd9f9c8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1235,6 +1285,8 @@ golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9sn golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= +golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= @@ -1250,6 +1302,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= @@ -1322,7 +1376,11 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= +golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ= +golang.org/x/tools v0.5.0/go.mod h1:N+Kgy78s5I24c24dU8OfWNEotWjutIs8SnJvn5IDq+k= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846 h1:Vve/L0v7CXXuxUmaMGIEK/dEeq7uiqb5qBgQrZzIE7E= golang.org/x/tools v0.12.1-0.20230815132531-74c255bcf846/go.mod h1:Sc0INKfu04TlqNoRA1hgpFZbhYXHPr4V5DzpSBTPqQM= @@ -1484,6 +1542,7 @@ google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlba google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= diff --git a/pkg/daemon/coderepo/coderepo.go b/pkg/daemon/coderepo/coderepo.go index d12ee0f5..386820d0 100644 --- a/pkg/daemon/coderepo/coderepo.go +++ b/pkg/daemon/coderepo/coderepo.go @@ -31,6 +31,10 @@ import ( "github.com/go-sigma/sigma/pkg/utils" ) +const ( + perPage = 100 +) + func init() { utils.PanicIf(daemon.RegisterTask(enums.DaemonCodeRepository, crRunner)) } diff --git a/pkg/daemon/coderepo/diff.go b/pkg/daemon/coderepo/diff.go index 27ac552b..a7480034 100644 --- a/pkg/daemon/coderepo/diff.go +++ b/pkg/daemon/coderepo/diff.go @@ -25,7 +25,7 @@ import ( "github.com/go-sigma/sigma/pkg/dal/query" ) -func (cr codeRepository) diff(ctx context.Context, user3rdPartyObj *models.User3rdParty, newRepos []*models.CodeRepository) error { +func (cr codeRepository) diff(ctx context.Context, user3rdPartyObj *models.User3rdParty, newRepos []*models.CodeRepository, branchMap map[string][]*models.CodeRepositoryBranch) error { codeRepositoryService := cr.codeRepositoryServiceFactory.New() oldRepos, err := codeRepositoryService.ListAll(ctx, user3rdPartyObj.ID) if err != nil { @@ -170,5 +170,81 @@ func (cr codeRepository) diff(ctx context.Context, user3rdPartyObj *models.User3 if err != nil { return err } - return nil + return cr.diffBranch(ctx, user3rdPartyObj, branchMap) +} + +func (cr codeRepository) diffBranch(ctx context.Context, user3rdPartyObj *models.User3rdParty, branchMap map[string][]*models.CodeRepositoryBranch) error { + if len(branchMap) == 0 { + return nil + } + codeRepositoryService := cr.codeRepositoryServiceFactory.New() + repositoryObjs, err := codeRepositoryService.ListAll(ctx, user3rdPartyObj.ID) + if err != nil { + log.Error().Err(err).Msg("List all repositories failed") + return fmt.Errorf("List all repositories failed: %v", err) + } + + var needInsertBranches []*models.CodeRepositoryBranch + var needDelBranches []int64 + for _, repo := range repositoryObjs { + oldBranches, _, err := codeRepositoryService.ListBranchesWithoutPagination(ctx, repo.ID) + if err != nil { + log.Error().Err(err).Int64("id", repo.ID).Msg("List repo branches failed") + return fmt.Errorf("List repo branches failed: %v", err) + } + if len(branchMap[repo.RepositoryID]) == 0 { + var bs []*models.CodeRepositoryBranch + for _, b := range branchMap[repo.RepositoryID] { + bs = append(bs, &models.CodeRepositoryBranch{CodeRepositoryID: repo.ID, Name: b.Name}) + } + needInsertBranches = append(needInsertBranches, bs...) + continue + } + + for _, oldB := range oldBranches { + found := false + for _, newB := range branchMap[repo.RepositoryID] { + if newB.Name == oldB.Name { + found = true + } + } + if !found { + needDelBranches = append(needDelBranches, oldB.ID) + } + } + + for _, newB := range branchMap[repo.RepositoryID] { + found := false + for _, oldB := range oldBranches { + if newB.Name == oldB.Name { + found = true + } + } + if !found { + needInsertBranches = append(needInsertBranches, &models.CodeRepositoryBranch{ + CodeRepositoryID: repo.ID, + Name: newB.Name, + }) + } + } + } + err = query.Q.Transaction(func(tx *query.Query) error { + codeRepositoryService := cr.codeRepositoryServiceFactory.New(tx) + if len(needInsertBranches) > 0 { + err := codeRepositoryService.CreateBranchesInBatches(ctx, needInsertBranches) + if err != nil { + log.Error().Err(err).Msg("Create new branches failed") + return fmt.Errorf("Create new branches failed: %v", err) + } + } + if len(needDelBranches) > 0 { + err := codeRepositoryService.DeleteBranchesInBatches(ctx, needDelBranches) + if err != nil { + log.Error().Err(err).Msg("Delete branches failed") + return fmt.Errorf("Delete branches failed: %v", err) + } + } + return nil + }) + return err } diff --git a/pkg/daemon/coderepo/gitea.go b/pkg/daemon/coderepo/gitea.go index 0042fd9a..bff90a15 100644 --- a/pkg/daemon/coderepo/gitea.go +++ b/pkg/daemon/coderepo/gitea.go @@ -92,5 +92,5 @@ func (cr codeRepository) gitea(ctx context.Context, user3rdPartyObj *models.User }) } - return cr.diff(ctx, user3rdPartyObj, newRepos) + return cr.diff(ctx, user3rdPartyObj, newRepos, nil) } diff --git a/pkg/daemon/coderepo/github.go b/pkg/daemon/coderepo/github.go index 55d2f051..dd482987 100644 --- a/pkg/daemon/coderepo/github.go +++ b/pkg/daemon/coderepo/github.go @@ -22,15 +22,12 @@ import ( "github.com/google/go-github/v53/github" "github.com/rs/zerolog/log" + "k8s.io/apimachinery/pkg/util/sets" "github.com/go-sigma/sigma/pkg/dal/models" "github.com/go-sigma/sigma/pkg/utils/ptr" ) -const ( - perPage = 100 -) - func (cr codeRepository) github(ctx context.Context, user3rdPartyObj *models.User3rdParty) error { client := github.NewTokenClient(ctx, ptr.To(user3rdPartyObj.Token)) @@ -110,5 +107,44 @@ func (cr codeRepository) github(ctx context.Context, user3rdPartyObj *models.Use newRepos = append(newRepos, repo) } - return cr.diff(ctx, user3rdPartyObj, newRepos) + var blockedRepo = sets.NewString() + + var branchMap = make(map[string][]*models.CodeRepositoryBranch) + for _, r := range newRepos { + var branches []*models.CodeRepositoryBranch + page = 1 + for { + bs, _, err := client.Repositories.ListBranches(ctx, r.Owner, r.Name, &github.BranchListOptions{ListOptions: github.ListOptions{Page: page, PerPage: perPage}}) + if err != nil { + if strings.Contains(err.Error(), "Repository access blocked") { + blockedRepo.Insert(r.RepositoryID) + } else { + log.Error().Err(err).Str("owner", r.Owner).Str("repo", r.Name).Msg("List branches failed") + return fmt.Errorf("List branches for repo(%s/%s) failed: %v", r.Owner, r.Name, err) + } + } + var bsObj = make([]*models.CodeRepositoryBranch, 0, len(bs)) + for _, b := range bs { + bsObj = append(bsObj, &models.CodeRepositoryBranch{ + Name: b.GetName(), + }) + } + branches = append(branches, bsObj...) + if len(bs) < perPage { + break + } + page++ + } + branchMap[r.RepositoryID] = branches + } + + repoFiltered := make([]*models.CodeRepository, 0, len(newRepos)) + for _, r := range newRepos { + if blockedRepo.Has(r.RepositoryID) { + continue + } + repoFiltered = append(repoFiltered, r) + } + + return cr.diff(ctx, user3rdPartyObj, repoFiltered, branchMap) } diff --git a/pkg/daemon/coderepo/gitlab.go b/pkg/daemon/coderepo/gitlab.go index 49300a29..d7e7dc50 100644 --- a/pkg/daemon/coderepo/gitlab.go +++ b/pkg/daemon/coderepo/gitlab.go @@ -113,5 +113,30 @@ func (cr codeRepository) gitlab(ctx context.Context, user3rdPartyObj *models.Use newRepos = append(newRepos, repo) } - return cr.diff(ctx, user3rdPartyObj, newRepos) + var branchMap = make(map[string][]*models.CodeRepositoryBranch) + for _, r := range newRepos { + var branches []*models.CodeRepositoryBranch + page = 1 + for { + bs, _, err := client.Branches.ListBranches(r.RepositoryID, &gitlab.ListBranchesOptions{ListOptions: gitlab.ListOptions{Page: page, PerPage: perPage}}) + if err != nil { + log.Error().Err(err).Str("owner", r.Owner).Str("repo", r.Name).Msg("List branches failed") + return fmt.Errorf("List branches for repo(%s/%s) failed: %v", r.Owner, r.Name, err) + } + var bsObj = make([]*models.CodeRepositoryBranch, 0, len(bs)) + for _, b := range bs { + bsObj = append(bsObj, &models.CodeRepositoryBranch{ + Name: b.Name, + }) + } + branches = append(branches, bsObj...) + if len(bs) < perPage { + break + } + page++ + } + branchMap[r.RepositoryID] = branches + } + + return cr.diff(ctx, user3rdPartyObj, newRepos, branchMap) } diff --git a/pkg/dal/cmd/gen.go b/pkg/dal/cmd/gen.go index d7755b2a..1ba7bd03 100644 --- a/pkg/dal/cmd/gen.go +++ b/pkg/dal/cmd/gen.go @@ -32,6 +32,7 @@ func main() { models.User3rdParty{}, models.UserRecoverCode{}, models.CodeRepository{}, + models.CodeRepositoryBranch{}, models.CodeRepositoryOwner{}, models.CodeRepositoryCloneCredential{}, models.Audit{}, diff --git a/pkg/dal/dao/code_repository.go b/pkg/dal/dao/code_repository.go index 1368f35e..3a6b79c2 100644 --- a/pkg/dal/dao/code_repository.go +++ b/pkg/dal/dao/code_repository.go @@ -36,6 +36,8 @@ type CodeRepositoryService interface { CreateInBatches(ctx context.Context, codeRepositories []*models.CodeRepository) error // CreateOwnersInBatches creates new code repository owner records in the database CreateOwnersInBatches(ctx context.Context, codeRepositoryOwners []*models.CodeRepositoryOwner) error + // CreateBranchesInBatches ... + CreateBranchesInBatches(ctx context.Context, branches []*models.CodeRepositoryBranch) error // UpdateInBatches updates code repository records in the database UpdateInBatches(ctx context.Context, codeRepositories []*models.CodeRepository) error // UpdateOwnersInBatches updates code repository owner records in the database @@ -44,6 +46,8 @@ type CodeRepositoryService interface { DeleteInBatches(ctx context.Context, ids []int64) error // DeleteOwnerInBatches deletes code repository owner records in the database DeleteOwnerInBatches(ctx context.Context, ids []int64) error + // DeleteBranchesInBatches ... + 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) // ListOwnersAll lists all code repository owners records in the database @@ -52,6 +56,8 @@ type CodeRepositoryService interface { ListWithPagination(ctx context.Context, userID int64, provider enums.Provider, owner, name *string, pagination types.Pagination, sort types.Sortable) ([]*models.CodeRepository, int64, error) // ListOwnerWithoutPagination list code repositories without pagination ListOwnerWithoutPagination(ctx context.Context, userID int64, provider enums.Provider, owner *string) ([]*models.CodeRepositoryOwner, int64, error) + // ListBranchesWithoutPagination ... + ListBranchesWithoutPagination(ctx context.Context, codeRepositoryID int64) ([]*models.CodeRepositoryBranch, int64, error) } type codeRepositoryService struct { @@ -90,6 +96,11 @@ func (s *codeRepositoryService) CreateOwnersInBatches(ctx context.Context, codeR return s.tx.CodeRepositoryOwner.WithContext(ctx).CreateInBatches(codeRepositoryOwners, consts.InsertBatchSize) } +// CreateBranchesInBatches ... +func (s *codeRepositoryService) CreateBranchesInBatches(ctx context.Context, branches []*models.CodeRepositoryBranch) error { + return s.tx.CodeRepositoryBranch.WithContext(ctx).CreateInBatches(branches, consts.InsertBatchSize) +} + // UpdateInBatches updates code repository records in the database func (s *codeRepositoryService) UpdateInBatches(ctx context.Context, codeRepositories []*models.CodeRepository) error { for _, cr := range codeRepositories { @@ -148,6 +159,18 @@ func (s *codeRepositoryService) DeleteOwnerInBatches(ctx context.Context, ids [] return nil } +// DeleteBranchesInBatches ... +func (s *codeRepositoryService) DeleteBranchesInBatches(ctx context.Context, ids []int64) error { + if len(ids) == 0 { + return nil + } + _, err := s.tx.CodeRepositoryBranch.WithContext(ctx).Where(s.tx.CodeRepositoryBranch.ID.In(ids...)).Delete() + if err != nil { + return err + } + return nil +} + // ListAll lists all code repository records in the database func (s *codeRepositoryService) ListAll(ctx context.Context, user3rdPartyID int64) ([]*models.CodeRepository, error) { return s.tx.CodeRepository.WithContext(ctx).Where(s.tx.CodeRepository.User3rdPartyID.Eq(user3rdPartyID)).Find() @@ -203,3 +226,8 @@ func (s *codeRepositoryService) ListOwnerWithoutPagination(ctx context.Context, return query.FindByPage(-1, -1) } + +// ListBranchesWithoutPagination ... +func (s *codeRepositoryService) ListBranchesWithoutPagination(ctx context.Context, codeRepositoryID int64) ([]*models.CodeRepositoryBranch, int64, error) { + return s.tx.CodeRepositoryBranch.WithContext(ctx).Where(s.tx.CodeRepositoryBranch.CodeRepositoryID.Eq(codeRepositoryID)).FindByPage(-1, -1) +} diff --git a/pkg/dal/dao/mocks/code_repository.go b/pkg/dal/dao/mocks/code_repository.go index b0e9647c..72b797bc 100644 --- a/pkg/dal/dao/mocks/code_repository.go +++ b/pkg/dal/dao/mocks/code_repository.go @@ -37,6 +37,20 @@ func (m *MockCodeRepositoryService) EXPECT() *MockCodeRepositoryServiceMockRecor return m.recorder } +// CreateBranchesInBatches mocks base method. +func (m *MockCodeRepositoryService) CreateBranchesInBatches(arg0 context.Context, arg1 []*models.CodeRepositoryBranch) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateBranchesInBatches", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateBranchesInBatches indicates an expected call of CreateBranchesInBatches. +func (mr *MockCodeRepositoryServiceMockRecorder) CreateBranchesInBatches(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateBranchesInBatches", reflect.TypeOf((*MockCodeRepositoryService)(nil).CreateBranchesInBatches), arg0, arg1) +} + // CreateInBatches mocks base method. func (m *MockCodeRepositoryService) CreateInBatches(arg0 context.Context, arg1 []*models.CodeRepository) error { m.ctrl.T.Helper() @@ -65,6 +79,20 @@ func (mr *MockCodeRepositoryServiceMockRecorder) CreateOwnersInBatches(arg0, arg return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOwnersInBatches", reflect.TypeOf((*MockCodeRepositoryService)(nil).CreateOwnersInBatches), arg0, arg1) } +// DeleteBranchesInBatches mocks base method. +func (m *MockCodeRepositoryService) DeleteBranchesInBatches(arg0 context.Context, arg1 []int64) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteBranchesInBatches", arg0, arg1) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteBranchesInBatches indicates an expected call of DeleteBranchesInBatches. +func (mr *MockCodeRepositoryServiceMockRecorder) DeleteBranchesInBatches(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBranchesInBatches", reflect.TypeOf((*MockCodeRepositoryService)(nil).DeleteBranchesInBatches), arg0, arg1) +} + // DeleteInBatches mocks base method. func (m *MockCodeRepositoryService) DeleteInBatches(arg0 context.Context, arg1 []int64) error { m.ctrl.T.Helper() @@ -108,6 +136,22 @@ func (mr *MockCodeRepositoryServiceMockRecorder) ListAll(arg0, arg1 interface{}) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListAll", reflect.TypeOf((*MockCodeRepositoryService)(nil).ListAll), arg0, arg1) } +// ListBranchesWithoutPagination mocks base method. +func (m *MockCodeRepositoryService) ListBranchesWithoutPagination(arg0 context.Context, arg1 int64) ([]*models.CodeRepositoryBranch, int64, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ListBranchesWithoutPagination", arg0, arg1) + ret0, _ := ret[0].([]*models.CodeRepositoryBranch) + ret1, _ := ret[1].(int64) + ret2, _ := ret[2].(error) + return ret0, ret1, ret2 +} + +// ListBranchesWithoutPagination indicates an expected call of ListBranchesWithoutPagination. +func (mr *MockCodeRepositoryServiceMockRecorder) ListBranchesWithoutPagination(arg0, arg1 interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ListBranchesWithoutPagination", reflect.TypeOf((*MockCodeRepositoryService)(nil).ListBranchesWithoutPagination), arg0, arg1) +} + // ListOwnerWithoutPagination mocks base method. func (m *MockCodeRepositoryService) ListOwnerWithoutPagination(arg0 context.Context, arg1 int64, arg2 enums.Provider, arg3 *string) ([]*models.CodeRepositoryOwner, int64, error) { m.ctrl.T.Helper() diff --git a/pkg/dal/migrations/mysql/0001_initialize.up.sql b/pkg/dal/migrations/mysql/0001_initialize.up.sql index 241eff47..dc63bd66 100644 --- a/pkg/dal/migrations/mysql/0001_initialize.up.sql +++ b/pkg/dal/migrations/mysql/0001_initialize.up.sql @@ -71,6 +71,17 @@ CREATE TABLE IF NOT EXISTS `code_repositories` ( CONSTRAINT `code_repositories_unique_with_name` UNIQUE (`user_3rdparty_id`, `owner_id`, `repository_id`, `deleted_at`) ); +CREATE TABLE IF NOT EXISTS `code_repository_branches` ( + `id` bigint AUTO_INCREMENT PRIMARY KEY, + `code_repository_id` bigint NOT NULL, + `name` varchar(256) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` bigint NOT NULL DEFAULT 0, + FOREIGN KEY (`code_repository_id`) REFERENCES `code_repositories` (`id`), + CONSTRAINT `code_repository_branches_unique_with_name` UNIQUE (`code_repository_id`, `name`, `deleted_at`) +); + CREATE TABLE IF NOT EXISTS `user_recover_codes` ( `id` bigint AUTO_INCREMENT PRIMARY KEY, `user_id` bigint NOT NULL, diff --git a/pkg/dal/migrations/postgresql/0001_initialize.up.sql b/pkg/dal/migrations/postgresql/0001_initialize.up.sql index bb16d6b0..64b94875 100644 --- a/pkg/dal/migrations/postgresql/0001_initialize.up.sql +++ b/pkg/dal/migrations/postgresql/0001_initialize.up.sql @@ -91,6 +91,17 @@ CREATE TABLE IF NOT EXISTS "code_repositories" ( CONSTRAINT "code_repositories_unique_with_name" UNIQUE ("user_3rdparty_id", "owner_id", "repository_id", "deleted_at") ); +CREATE TABLE IF NOT EXISTS "code_repository_branches" ( + "id" bigserial PRIMARY KEY, + "code_repository_id" integer NOT NULL, + "name" varchar(256) NOT NULL, + "created_at" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updated_at" timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deleted_at" integer NOT NULL DEFAULT 0, + FOREIGN KEY ("code_repository_id") REFERENCES "code_repositories" ("id"), + CONSTRAINT "code_repository_branches_unique_with_name" UNIQUE ("code_repository_id", "name", "deleted_at") +); + CREATE TABLE IF NOT EXISTS "user_recover_codes" ( "id" bigserial PRIMARY KEY, "user_id" bigint NOT NULL, diff --git a/pkg/dal/migrations/sqlite3/0001_initialize.up.sql b/pkg/dal/migrations/sqlite3/0001_initialize.up.sql index 716288cd..73d608be 100644 --- a/pkg/dal/migrations/sqlite3/0001_initialize.up.sql +++ b/pkg/dal/migrations/sqlite3/0001_initialize.up.sql @@ -55,7 +55,7 @@ CREATE TABLE IF NOT EXISTS `code_repository_owners` ( CREATE TABLE IF NOT EXISTS `code_repositories` ( `id` integer PRIMARY KEY AUTOINCREMENT, - `user_3rdparty_id` bigint NOT NULL, + `user_3rdparty_id` integer NOT NULL, `repository_id` varchar(256) NOT NULL, `is_org` integer NOT NULL DEFAULT 0, `owner_id` varchar(256) NOT NULL, @@ -66,11 +66,22 @@ CREATE TABLE IF NOT EXISTS `code_repositories` ( `oci_repo_count` integer NOT NULL DEFAULT 0, `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, - `deleted_at` bigint NOT NULL DEFAULT 0, + `deleted_at` integer NOT NULL DEFAULT 0, FOREIGN KEY (`user_3rdparty_id`) REFERENCES `user_3rdparty` (`id`), CONSTRAINT `code_repositories_unique_with_name` UNIQUE (`user_3rdparty_id`, `owner_id`, `repository_id`, `deleted_at`) ); +CREATE TABLE IF NOT EXISTS `code_repository_branches` ( + `id` integer PRIMARY KEY AUTOINCREMENT, + `code_repository_id` integer NOT NULL, + `name` varchar(256) NOT NULL, + `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, + `deleted_at` integer NOT NULL DEFAULT 0, + FOREIGN KEY (`code_repository_id`) REFERENCES `code_repositories` (`id`), + CONSTRAINT `code_repository_branches_unique_with_name` UNIQUE (`code_repository_id`, `name`, `deleted_at`) +); + CREATE TABLE IF NOT EXISTS `user_recover_codes` ( `id` integer PRIMARY KEY AUTOINCREMENT, `user_id` integer NOT NULL, diff --git a/pkg/dal/models/code_repository.go b/pkg/dal/models/code_repository.go index d56cd23e..61cdb50d 100644 --- a/pkg/dal/models/code_repository.go +++ b/pkg/dal/models/code_repository.go @@ -42,6 +42,18 @@ type CodeRepository struct { OciRepoCount int64 User3rdParty User3rdParty `gorm:"foreignKey:User3rdPartyID"` + Branches []CodeRepositoryBranch +} + +// CodeRepositoryBranch ... +type CodeRepositoryBranch struct { + CreatedAt time.Time + UpdatedAt time.Time + DeletedAt soft_delete.DeletedAt `gorm:"softDelete:milli"` + ID int64 `gorm:"primaryKey"` + + CodeRepositoryID int64 + Name string } // CodeRepositoryOwner ... diff --git a/pkg/dal/query/code_repositories.gen.go b/pkg/dal/query/code_repositories.gen.go index bbc0fafe..0d48cf00 100644 --- a/pkg/dal/query/code_repositories.gen.go +++ b/pkg/dal/query/code_repositories.gen.go @@ -40,6 +40,12 @@ func newCodeRepository(db *gorm.DB, opts ...gen.DOOption) codeRepository { _codeRepository.SshUrl = field.NewString(tableName, "ssh_url") _codeRepository.CloneUrl = field.NewString(tableName, "clone_url") _codeRepository.OciRepoCount = field.NewInt64(tableName, "oci_repo_count") + _codeRepository.Branches = codeRepositoryHasManyBranches{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("Branches", "models.CodeRepositoryBranch"), + } + _codeRepository.User3rdParty = codeRepositoryBelongsToUser3rdParty{ db: db.Session(&gorm.Session{}), @@ -73,7 +79,9 @@ type codeRepository struct { SshUrl field.String CloneUrl field.String OciRepoCount field.Int64 - User3rdParty codeRepositoryBelongsToUser3rdParty + Branches codeRepositoryHasManyBranches + + User3rdParty codeRepositoryBelongsToUser3rdParty fieldMap map[string]field.Expr } @@ -131,7 +139,7 @@ func (c *codeRepository) GetFieldByName(fieldName string) (field.OrderExpr, bool } func (c *codeRepository) fillFieldMap() { - c.fieldMap = make(map[string]field.Expr, 14) + c.fieldMap = make(map[string]field.Expr, 15) c.fieldMap["created_at"] = c.CreatedAt c.fieldMap["updated_at"] = c.UpdatedAt c.fieldMap["deleted_at"] = c.DeletedAt @@ -158,6 +166,77 @@ func (c codeRepository) replaceDB(db *gorm.DB) codeRepository { return c } +type codeRepositoryHasManyBranches struct { + db *gorm.DB + + field.RelationField +} + +func (a codeRepositoryHasManyBranches) Where(conds ...field.Expr) *codeRepositoryHasManyBranches { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a codeRepositoryHasManyBranches) WithContext(ctx context.Context) *codeRepositoryHasManyBranches { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a codeRepositoryHasManyBranches) Session(session *gorm.Session) *codeRepositoryHasManyBranches { + a.db = a.db.Session(session) + return &a +} + +func (a codeRepositoryHasManyBranches) Model(m *models.CodeRepository) *codeRepositoryHasManyBranchesTx { + return &codeRepositoryHasManyBranchesTx{a.db.Model(m).Association(a.Name())} +} + +type codeRepositoryHasManyBranchesTx struct{ tx *gorm.Association } + +func (a codeRepositoryHasManyBranchesTx) Find() (result []*models.CodeRepositoryBranch, err error) { + return result, a.tx.Find(&result) +} + +func (a codeRepositoryHasManyBranchesTx) Append(values ...*models.CodeRepositoryBranch) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a codeRepositoryHasManyBranchesTx) Replace(values ...*models.CodeRepositoryBranch) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a codeRepositoryHasManyBranchesTx) Delete(values ...*models.CodeRepositoryBranch) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a codeRepositoryHasManyBranchesTx) Clear() error { + return a.tx.Clear() +} + +func (a codeRepositoryHasManyBranchesTx) Count() int64 { + return a.tx.Count() +} + type codeRepositoryBelongsToUser3rdParty struct { db *gorm.DB diff --git a/pkg/dal/query/code_repository_branches.gen.go b/pkg/dal/query/code_repository_branches.gen.go new file mode 100644 index 00000000..920e504b --- /dev/null +++ b/pkg/dal/query/code_repository_branches.gen.go @@ -0,0 +1,351 @@ +// 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 newCodeRepositoryBranch(db *gorm.DB, opts ...gen.DOOption) codeRepositoryBranch { + _codeRepositoryBranch := codeRepositoryBranch{} + + _codeRepositoryBranch.codeRepositoryBranchDo.UseDB(db, opts...) + _codeRepositoryBranch.codeRepositoryBranchDo.UseModel(&models.CodeRepositoryBranch{}) + + tableName := _codeRepositoryBranch.codeRepositoryBranchDo.TableName() + _codeRepositoryBranch.ALL = field.NewAsterisk(tableName) + _codeRepositoryBranch.CreatedAt = field.NewTime(tableName, "created_at") + _codeRepositoryBranch.UpdatedAt = field.NewTime(tableName, "updated_at") + _codeRepositoryBranch.DeletedAt = field.NewUint(tableName, "deleted_at") + _codeRepositoryBranch.ID = field.NewInt64(tableName, "id") + _codeRepositoryBranch.CodeRepositoryID = field.NewInt64(tableName, "code_repository_id") + _codeRepositoryBranch.Name = field.NewString(tableName, "name") + + _codeRepositoryBranch.fillFieldMap() + + return _codeRepositoryBranch +} + +type codeRepositoryBranch struct { + codeRepositoryBranchDo codeRepositoryBranchDo + + ALL field.Asterisk + CreatedAt field.Time + UpdatedAt field.Time + DeletedAt field.Uint + ID field.Int64 + CodeRepositoryID field.Int64 + Name field.String + + fieldMap map[string]field.Expr +} + +func (c codeRepositoryBranch) Table(newTableName string) *codeRepositoryBranch { + c.codeRepositoryBranchDo.UseTable(newTableName) + return c.updateTableName(newTableName) +} + +func (c codeRepositoryBranch) As(alias string) *codeRepositoryBranch { + c.codeRepositoryBranchDo.DO = *(c.codeRepositoryBranchDo.As(alias).(*gen.DO)) + return c.updateTableName(alias) +} + +func (c *codeRepositoryBranch) updateTableName(table string) *codeRepositoryBranch { + c.ALL = field.NewAsterisk(table) + c.CreatedAt = field.NewTime(table, "created_at") + c.UpdatedAt = field.NewTime(table, "updated_at") + c.DeletedAt = field.NewUint(table, "deleted_at") + c.ID = field.NewInt64(table, "id") + c.CodeRepositoryID = field.NewInt64(table, "code_repository_id") + c.Name = field.NewString(table, "name") + + c.fillFieldMap() + + return c +} + +func (c *codeRepositoryBranch) WithContext(ctx context.Context) *codeRepositoryBranchDo { + return c.codeRepositoryBranchDo.WithContext(ctx) +} + +func (c codeRepositoryBranch) TableName() string { return c.codeRepositoryBranchDo.TableName() } + +func (c codeRepositoryBranch) Alias() string { return c.codeRepositoryBranchDo.Alias() } + +func (c codeRepositoryBranch) Columns(cols ...field.Expr) gen.Columns { + return c.codeRepositoryBranchDo.Columns(cols...) +} + +func (c *codeRepositoryBranch) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := c.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (c *codeRepositoryBranch) fillFieldMap() { + c.fieldMap = make(map[string]field.Expr, 6) + c.fieldMap["created_at"] = c.CreatedAt + c.fieldMap["updated_at"] = c.UpdatedAt + c.fieldMap["deleted_at"] = c.DeletedAt + c.fieldMap["id"] = c.ID + c.fieldMap["code_repository_id"] = c.CodeRepositoryID + c.fieldMap["name"] = c.Name +} + +func (c codeRepositoryBranch) clone(db *gorm.DB) codeRepositoryBranch { + c.codeRepositoryBranchDo.ReplaceConnPool(db.Statement.ConnPool) + return c +} + +func (c codeRepositoryBranch) replaceDB(db *gorm.DB) codeRepositoryBranch { + c.codeRepositoryBranchDo.ReplaceDB(db) + return c +} + +type codeRepositoryBranchDo struct{ gen.DO } + +func (c codeRepositoryBranchDo) Debug() *codeRepositoryBranchDo { + return c.withDO(c.DO.Debug()) +} + +func (c codeRepositoryBranchDo) WithContext(ctx context.Context) *codeRepositoryBranchDo { + return c.withDO(c.DO.WithContext(ctx)) +} + +func (c codeRepositoryBranchDo) ReadDB() *codeRepositoryBranchDo { + return c.Clauses(dbresolver.Read) +} + +func (c codeRepositoryBranchDo) WriteDB() *codeRepositoryBranchDo { + return c.Clauses(dbresolver.Write) +} + +func (c codeRepositoryBranchDo) Session(config *gorm.Session) *codeRepositoryBranchDo { + return c.withDO(c.DO.Session(config)) +} + +func (c codeRepositoryBranchDo) Clauses(conds ...clause.Expression) *codeRepositoryBranchDo { + return c.withDO(c.DO.Clauses(conds...)) +} + +func (c codeRepositoryBranchDo) Returning(value interface{}, columns ...string) *codeRepositoryBranchDo { + return c.withDO(c.DO.Returning(value, columns...)) +} + +func (c codeRepositoryBranchDo) Not(conds ...gen.Condition) *codeRepositoryBranchDo { + return c.withDO(c.DO.Not(conds...)) +} + +func (c codeRepositoryBranchDo) Or(conds ...gen.Condition) *codeRepositoryBranchDo { + return c.withDO(c.DO.Or(conds...)) +} + +func (c codeRepositoryBranchDo) Select(conds ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Select(conds...)) +} + +func (c codeRepositoryBranchDo) Where(conds ...gen.Condition) *codeRepositoryBranchDo { + return c.withDO(c.DO.Where(conds...)) +} + +func (c codeRepositoryBranchDo) Order(conds ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Order(conds...)) +} + +func (c codeRepositoryBranchDo) Distinct(cols ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Distinct(cols...)) +} + +func (c codeRepositoryBranchDo) Omit(cols ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Omit(cols...)) +} + +func (c codeRepositoryBranchDo) Join(table schema.Tabler, on ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Join(table, on...)) +} + +func (c codeRepositoryBranchDo) LeftJoin(table schema.Tabler, on ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.LeftJoin(table, on...)) +} + +func (c codeRepositoryBranchDo) RightJoin(table schema.Tabler, on ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.RightJoin(table, on...)) +} + +func (c codeRepositoryBranchDo) Group(cols ...field.Expr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Group(cols...)) +} + +func (c codeRepositoryBranchDo) Having(conds ...gen.Condition) *codeRepositoryBranchDo { + return c.withDO(c.DO.Having(conds...)) +} + +func (c codeRepositoryBranchDo) Limit(limit int) *codeRepositoryBranchDo { + return c.withDO(c.DO.Limit(limit)) +} + +func (c codeRepositoryBranchDo) Offset(offset int) *codeRepositoryBranchDo { + return c.withDO(c.DO.Offset(offset)) +} + +func (c codeRepositoryBranchDo) Scopes(funcs ...func(gen.Dao) gen.Dao) *codeRepositoryBranchDo { + return c.withDO(c.DO.Scopes(funcs...)) +} + +func (c codeRepositoryBranchDo) Unscoped() *codeRepositoryBranchDo { + return c.withDO(c.DO.Unscoped()) +} + +func (c codeRepositoryBranchDo) Create(values ...*models.CodeRepositoryBranch) error { + if len(values) == 0 { + return nil + } + return c.DO.Create(values) +} + +func (c codeRepositoryBranchDo) CreateInBatches(values []*models.CodeRepositoryBranch, batchSize int) error { + return c.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 (c codeRepositoryBranchDo) Save(values ...*models.CodeRepositoryBranch) error { + if len(values) == 0 { + return nil + } + return c.DO.Save(values) +} + +func (c codeRepositoryBranchDo) First() (*models.CodeRepositoryBranch, error) { + if result, err := c.DO.First(); err != nil { + return nil, err + } else { + return result.(*models.CodeRepositoryBranch), nil + } +} + +func (c codeRepositoryBranchDo) Take() (*models.CodeRepositoryBranch, error) { + if result, err := c.DO.Take(); err != nil { + return nil, err + } else { + return result.(*models.CodeRepositoryBranch), nil + } +} + +func (c codeRepositoryBranchDo) Last() (*models.CodeRepositoryBranch, error) { + if result, err := c.DO.Last(); err != nil { + return nil, err + } else { + return result.(*models.CodeRepositoryBranch), nil + } +} + +func (c codeRepositoryBranchDo) Find() ([]*models.CodeRepositoryBranch, error) { + result, err := c.DO.Find() + return result.([]*models.CodeRepositoryBranch), err +} + +func (c codeRepositoryBranchDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.CodeRepositoryBranch, err error) { + buf := make([]*models.CodeRepositoryBranch, 0, batchSize) + err = c.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 (c codeRepositoryBranchDo) FindInBatches(result *[]*models.CodeRepositoryBranch, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return c.DO.FindInBatches(result, batchSize, fc) +} + +func (c codeRepositoryBranchDo) Attrs(attrs ...field.AssignExpr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Attrs(attrs...)) +} + +func (c codeRepositoryBranchDo) Assign(attrs ...field.AssignExpr) *codeRepositoryBranchDo { + return c.withDO(c.DO.Assign(attrs...)) +} + +func (c codeRepositoryBranchDo) Joins(fields ...field.RelationField) *codeRepositoryBranchDo { + for _, _f := range fields { + c = *c.withDO(c.DO.Joins(_f)) + } + return &c +} + +func (c codeRepositoryBranchDo) Preload(fields ...field.RelationField) *codeRepositoryBranchDo { + for _, _f := range fields { + c = *c.withDO(c.DO.Preload(_f)) + } + return &c +} + +func (c codeRepositoryBranchDo) FirstOrInit() (*models.CodeRepositoryBranch, error) { + if result, err := c.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*models.CodeRepositoryBranch), nil + } +} + +func (c codeRepositoryBranchDo) FirstOrCreate() (*models.CodeRepositoryBranch, error) { + if result, err := c.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*models.CodeRepositoryBranch), nil + } +} + +func (c codeRepositoryBranchDo) FindByPage(offset int, limit int) (result []*models.CodeRepositoryBranch, count int64, err error) { + result, err = c.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 = c.Offset(-1).Limit(-1).Count() + return +} + +func (c codeRepositoryBranchDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = c.Count() + if err != nil { + return + } + + err = c.Offset(offset).Limit(limit).Scan(result) + return +} + +func (c codeRepositoryBranchDo) Scan(result interface{}) (err error) { + return c.DO.Scan(result) +} + +func (c codeRepositoryBranchDo) Delete(models ...*models.CodeRepositoryBranch) (result gen.ResultInfo, err error) { + return c.DO.Delete(models) +} + +func (c *codeRepositoryBranchDo) withDO(do gen.Dao) *codeRepositoryBranchDo { + c.DO = *do.(*gen.DO) + return c +} diff --git a/pkg/dal/query/gen.go b/pkg/dal/query/gen.go index 8515cc48..bf97281a 100644 --- a/pkg/dal/query/gen.go +++ b/pkg/dal/query/gen.go @@ -27,6 +27,7 @@ var ( BuilderRunner *builderRunner CasbinRule *casbinRule CodeRepository *codeRepository + CodeRepositoryBranch *codeRepositoryBranch CodeRepositoryCloneCredential *codeRepositoryCloneCredential CodeRepositoryOwner *codeRepositoryOwner DaemonLog *daemonLog @@ -52,6 +53,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) { BuilderRunner = &Q.BuilderRunner CasbinRule = &Q.CasbinRule CodeRepository = &Q.CodeRepository + CodeRepositoryBranch = &Q.CodeRepositoryBranch CodeRepositoryCloneCredential = &Q.CodeRepositoryCloneCredential CodeRepositoryOwner = &Q.CodeRepositoryOwner DaemonLog = &Q.DaemonLog @@ -78,6 +80,7 @@ func Use(db *gorm.DB, opts ...gen.DOOption) *Query { BuilderRunner: newBuilderRunner(db, opts...), CasbinRule: newCasbinRule(db, opts...), CodeRepository: newCodeRepository(db, opts...), + CodeRepositoryBranch: newCodeRepositoryBranch(db, opts...), CodeRepositoryCloneCredential: newCodeRepositoryCloneCredential(db, opts...), CodeRepositoryOwner: newCodeRepositoryOwner(db, opts...), DaemonLog: newDaemonLog(db, opts...), @@ -105,6 +108,7 @@ type Query struct { BuilderRunner builderRunner CasbinRule casbinRule CodeRepository codeRepository + CodeRepositoryBranch codeRepositoryBranch CodeRepositoryCloneCredential codeRepositoryCloneCredential CodeRepositoryOwner codeRepositoryOwner DaemonLog daemonLog @@ -133,6 +137,7 @@ func (q *Query) clone(db *gorm.DB) *Query { BuilderRunner: q.BuilderRunner.clone(db), CasbinRule: q.CasbinRule.clone(db), CodeRepository: q.CodeRepository.clone(db), + CodeRepositoryBranch: q.CodeRepositoryBranch.clone(db), CodeRepositoryCloneCredential: q.CodeRepositoryCloneCredential.clone(db), CodeRepositoryOwner: q.CodeRepositoryOwner.clone(db), DaemonLog: q.DaemonLog.clone(db), @@ -168,6 +173,7 @@ func (q *Query) ReplaceDB(db *gorm.DB) *Query { BuilderRunner: q.BuilderRunner.replaceDB(db), CasbinRule: q.CasbinRule.replaceDB(db), CodeRepository: q.CodeRepository.replaceDB(db), + CodeRepositoryBranch: q.CodeRepositoryBranch.replaceDB(db), CodeRepositoryCloneCredential: q.CodeRepositoryCloneCredential.replaceDB(db), CodeRepositoryOwner: q.CodeRepositoryOwner.replaceDB(db), DaemonLog: q.DaemonLog.replaceDB(db), @@ -193,6 +199,7 @@ type queryCtx struct { BuilderRunner *builderRunnerDo CasbinRule *casbinRuleDo CodeRepository *codeRepositoryDo + CodeRepositoryBranch *codeRepositoryBranchDo CodeRepositoryCloneCredential *codeRepositoryCloneCredentialDo CodeRepositoryOwner *codeRepositoryOwnerDo DaemonLog *daemonLogDo @@ -218,6 +225,7 @@ func (q *Query) WithContext(ctx context.Context) *queryCtx { BuilderRunner: q.BuilderRunner.WithContext(ctx), CasbinRule: q.CasbinRule.WithContext(ctx), CodeRepository: q.CodeRepository.WithContext(ctx), + CodeRepositoryBranch: q.CodeRepositoryBranch.WithContext(ctx), CodeRepositoryCloneCredential: q.CodeRepositoryCloneCredential.WithContext(ctx), CodeRepositoryOwner: q.CodeRepositoryOwner.WithContext(ctx), DaemonLog: q.DaemonLog.WithContext(ctx), diff --git a/pkg/dal/query/user_3rdparty.gen.go b/pkg/dal/query/user_3rdparty.gen.go index e4e320da..c4448739 100644 --- a/pkg/dal/query/user_3rdparty.gen.go +++ b/pkg/dal/query/user_3rdparty.gen.go @@ -52,6 +52,7 @@ func newUser3rdParty(db *gorm.DB, opts ...gen.DOOption) user3rdParty { type user3rdParty struct { user3rdPartyDo user3rdPartyDo + ALL field.Asterisk CreatedAt field.Time UpdatedAt field.Time diff --git a/pkg/handlers/apidocs/docs.go b/pkg/handlers/apidocs/docs.go index 4b8c7077..b712481a 100644 --- a/pkg/handlers/apidocs/docs.go +++ b/pkg/handlers/apidocs/docs.go @@ -83,7 +83,7 @@ const docTemplate = `{ } } }, - "/coderepos/providers/": { + "/coderepos/providers": { "get": { "security": [ { @@ -137,6 +137,63 @@ const docTemplate = `{ } } }, + "/coderepos/{id}/branches": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CodeRepository" + ], + "summary": "List code repository branches", + "parameters": [ + { + "type": "string", + "description": "code repository id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/types.CommonList" + }, + { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/types.CodeRepositoryBranchItem" + } + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/xerrors.ErrCode" + } + } + } + } + }, "/coderepos/{id}/setup-builder": { "post": { "security": [ @@ -356,6 +413,87 @@ const docTemplate = `{ } } }, + "/coderepos/{provider}/resync": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CodeRepository" + ], + "summary": "Resync code repository", + "parameters": [ + { + "type": "string", + "description": "search code repository with provider", + "name": "provider", + "in": "path", + "required": true + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/xerrors.ErrCode" + } + } + } + } + }, + "/coderepos/{provider}/user3rdparty": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CodeRepository" + ], + "summary": "Get code repository user 3rdparty", + "parameters": [ + { + "type": "string", + "description": "get user 3rdParty with provider", + "name": "provider", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.GetCodeRepositoryUser3rdPartyResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/xerrors.ErrCode" + } + } + } + } + }, "/daemons/{daemon}/": { "get": { "consumes": [ @@ -2264,6 +2402,27 @@ const docTemplate = `{ "WebhookResourceTypeMember" ] }, + "types.CodeRepositoryBranchItem": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + }, + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "main" + }, + "updated_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + } + } + }, "types.CodeRepositoryItem": { "type": "object", "properties": { @@ -2391,6 +2550,36 @@ const docTemplate = `{ } } }, + "types.GetCodeRepositoryUser3rdPartyResponse": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "example": "1" + }, + "cr_last_update_message": { + "type": "string" + }, + "cr_last_update_status": { + "$ref": "#/definitions/enums.TaskCommonStatus" + }, + "cr_last_update_timestamp": { + "type": "string" + }, + "created_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + }, + "id": { + "type": "integer", + "example": 1 + }, + "updated_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + } + } + }, "types.GetEndpointResponse": { "type": "object", "properties": { @@ -2543,7 +2732,7 @@ const docTemplate = `{ "types.ListCodeRepositoryProvidersResponse": { "type": "object", "properties": { - "providers": { + "provider": { "allOf": [ { "$ref": "#/definitions/enums.Provider" diff --git a/pkg/handlers/apidocs/swagger.json b/pkg/handlers/apidocs/swagger.json index 03087b0f..8fa5f45c 100644 --- a/pkg/handlers/apidocs/swagger.json +++ b/pkg/handlers/apidocs/swagger.json @@ -74,7 +74,7 @@ } } }, - "/coderepos/providers/": { + "/coderepos/providers": { "get": { "security": [ { @@ -128,6 +128,63 @@ } } }, + "/coderepos/{id}/branches": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CodeRepository" + ], + "summary": "List code repository branches", + "parameters": [ + { + "type": "string", + "description": "code repository id", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "allOf": [ + { + "$ref": "#/definitions/types.CommonList" + }, + { + "type": "object", + "properties": { + "items": { + "type": "array", + "items": { + "$ref": "#/definitions/types.CodeRepositoryBranchItem" + } + } + } + } + ] + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/xerrors.ErrCode" + } + } + } + } + }, "/coderepos/{id}/setup-builder": { "post": { "security": [ @@ -347,6 +404,87 @@ } } }, + "/coderepos/{provider}/resync": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CodeRepository" + ], + "summary": "Resync code repository", + "parameters": [ + { + "type": "string", + "description": "search code repository with provider", + "name": "provider", + "in": "path", + "required": true + } + ], + "responses": { + "202": { + "description": "Accepted" + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/xerrors.ErrCode" + } + } + } + } + }, + "/coderepos/{provider}/user3rdparty": { + "get": { + "security": [ + { + "BasicAuth": [] + } + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "CodeRepository" + ], + "summary": "Get code repository user 3rdparty", + "parameters": [ + { + "type": "string", + "description": "get user 3rdParty with provider", + "name": "provider", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/types.GetCodeRepositoryUser3rdPartyResponse" + } + }, + "500": { + "description": "Internal Server Error", + "schema": { + "$ref": "#/definitions/xerrors.ErrCode" + } + } + } + } + }, "/daemons/{daemon}/": { "get": { "consumes": [ @@ -2255,6 +2393,27 @@ "WebhookResourceTypeMember" ] }, + "types.CodeRepositoryBranchItem": { + "type": "object", + "properties": { + "created_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + }, + "id": { + "type": "integer", + "example": 1 + }, + "name": { + "type": "string", + "example": "main" + }, + "updated_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + } + } + }, "types.CodeRepositoryItem": { "type": "object", "properties": { @@ -2382,6 +2541,36 @@ } } }, + "types.GetCodeRepositoryUser3rdPartyResponse": { + "type": "object", + "properties": { + "account_id": { + "type": "string", + "example": "1" + }, + "cr_last_update_message": { + "type": "string" + }, + "cr_last_update_status": { + "$ref": "#/definitions/enums.TaskCommonStatus" + }, + "cr_last_update_timestamp": { + "type": "string" + }, + "created_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + }, + "id": { + "type": "integer", + "example": 1 + }, + "updated_at": { + "type": "string", + "example": "2006-01-02 15:04:05" + } + } + }, "types.GetEndpointResponse": { "type": "object", "properties": { @@ -2534,7 +2723,7 @@ "types.ListCodeRepositoryProvidersResponse": { "type": "object", "properties": { - "providers": { + "provider": { "allOf": [ { "$ref": "#/definitions/enums.Provider" diff --git a/pkg/handlers/apidocs/swagger.yaml b/pkg/handlers/apidocs/swagger.yaml index a6399b6b..625d8e2f 100644 --- a/pkg/handlers/apidocs/swagger.yaml +++ b/pkg/handlers/apidocs/swagger.yaml @@ -120,6 +120,21 @@ definitions: - WebhookResourceTypeTag - WebhookResourceTypeArtifact - WebhookResourceTypeMember + types.CodeRepositoryBranchItem: + properties: + created_at: + example: "2006-01-02 15:04:05" + type: string + id: + example: 1 + type: integer + name: + example: main + type: string + updated_at: + example: "2006-01-02 15:04:05" + type: string + type: object types.CodeRepositoryItem: properties: clone_url: @@ -210,6 +225,27 @@ definitions: example: "2006-01-02 15:04:05" type: string type: object + types.GetCodeRepositoryUser3rdPartyResponse: + properties: + account_id: + example: "1" + type: string + cr_last_update_message: + type: string + cr_last_update_status: + $ref: '#/definitions/enums.TaskCommonStatus' + cr_last_update_timestamp: + type: string + created_at: + example: "2006-01-02 15:04:05" + type: string + id: + example: 1 + type: integer + updated_at: + example: "2006-01-02 15:04:05" + type: string + type: object types.GetEndpointResponse: properties: endpoint: @@ -316,7 +352,7 @@ definitions: type: object types.ListCodeRepositoryProvidersResponse: properties: - providers: + provider: allOf: - $ref: '#/definitions/enums.Provider' example: github @@ -895,6 +931,39 @@ paths: summary: Create a builder for repository tags: - Builder + /coderepos/{id}/branches: + get: + consumes: + - application/json + parameters: + - description: code repository id + in: path + name: id + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + allOf: + - $ref: '#/definitions/types.CommonList' + - properties: + items: + items: + $ref: '#/definitions/types.CodeRepositoryBranchItem' + type: array + type: object + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/xerrors.ErrCode' + security: + - BasicAuth: [] + summary: List code repository branches + tags: + - CodeRepository /coderepos/{id}/setup-builder: post: consumes: @@ -1031,7 +1100,57 @@ paths: summary: List code repository owners tags: - CodeRepository - /coderepos/providers/: + /coderepos/{provider}/resync: + get: + consumes: + - application/json + parameters: + - description: search code repository with provider + in: path + name: provider + required: true + type: string + produces: + - application/json + responses: + "202": + description: Accepted + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/xerrors.ErrCode' + security: + - BasicAuth: [] + summary: Resync code repository + tags: + - CodeRepository + /coderepos/{provider}/user3rdparty: + get: + consumes: + - application/json + parameters: + - description: get user 3rdParty with provider + in: path + name: provider + required: true + type: string + produces: + - application/json + responses: + "200": + description: OK + schema: + $ref: '#/definitions/types.GetCodeRepositoryUser3rdPartyResponse' + "500": + description: Internal Server Error + schema: + $ref: '#/definitions/xerrors.ErrCode' + security: + - BasicAuth: [] + summary: Get code repository user 3rdparty + tags: + - CodeRepository + /coderepos/providers: get: consumes: - application/json diff --git a/pkg/handlers/coderepos/coderepos_branches.go b/pkg/handlers/coderepos/coderepos_branches.go new file mode 100644 index 00000000..7353cef4 --- /dev/null +++ b/pkg/handlers/coderepos/coderepos_branches.go @@ -0,0 +1,53 @@ +package coderepos + +import ( + "fmt" + "net/http" + + "github.com/labstack/echo/v4" + "github.com/rs/zerolog/log" + + "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" +) + +// ListBranches list all of the branches +// @Summary List code repository branches +// @security BasicAuth +// @Tags CodeRepository +// @Accept json +// @Produce json +// @Router /coderepos/{id}/branches [get] +// @Param id path string true "code repository id" +// @Success 200 {object} types.CommonList{items=[]types.CodeRepositoryBranchItem} +// @Failure 500 {object} xerrors.ErrCode +func (h *handlers) ListBranches(c echo.Context) error { + ctx := log.Logger.WithContext(c.Request().Context()) + + var req types.ListCodeRepositoryBranchesRequest + 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, err.Error()) + } + + codeRepositoryService := h.codeRepositoryServiceFactory.New() + branchObjs, total, err := codeRepositoryService.ListBranchesWithoutPagination(ctx, req.ID) + if err != nil { + log.Error().Err(err).Msg("List branches failed") + return xerrors.NewHTTPError(c, xerrors.HTTPErrCodeInternalError, fmt.Sprintf("List branches failed: %v", err)) + } + resp := make([]any, 0, len(branchObjs)) + for _, branchObj := range branchObjs { + resp = append(resp, types.CodeRepositoryBranchItem{ + ID: branchObj.ID, + Name: branchObj.Name, + CreatedAt: branchObj.CreatedAt.Format(consts.DefaultTimePattern), + UpdatedAt: branchObj.UpdatedAt.Format(consts.DefaultTimePattern), + }) + } + + return c.JSON(http.StatusOK, types.CommonList{Total: total, Items: resp}) +} diff --git a/pkg/handlers/coderepos/coderepos_resync.go b/pkg/handlers/coderepos/coderepos_resync.go index 8039d40e..1c1d57e7 100644 --- a/pkg/handlers/coderepos/coderepos_resync.go +++ b/pkg/handlers/coderepos/coderepos_resync.go @@ -17,6 +17,7 @@ package coderepos import ( "errors" "fmt" + "net/http" "time" "github.com/labstack/echo/v4" @@ -34,6 +35,15 @@ import ( ) // Resync resync all of the code repositories +// @Summary Resync code repository +// @security BasicAuth +// @Tags CodeRepository +// @Accept json +// @Produce json +// @Router /coderepos/{provider}/resync [get] +// @Param provider path string true "search code repository with provider" +// @Success 202 +// @Failure 500 {object} xerrors.ErrCode func (h *handlers) Resync(c echo.Context) error { ctx := log.Logger.WithContext(c.Request().Context()) @@ -88,5 +98,5 @@ func (h *handlers) Resync(c echo.Context) error { if err != nil { return xerrors.NewHTTPError(c, err.(xerrors.ErrCode)) } - return nil + return c.NoContent(http.StatusAccepted) } diff --git a/pkg/handlers/coderepos/coderepos_user3rdparty.go b/pkg/handlers/coderepos/coderepos_user3rdparty.go index 60b81737..0c97acff 100644 --- a/pkg/handlers/coderepos/coderepos_user3rdparty.go +++ b/pkg/handlers/coderepos/coderepos_user3rdparty.go @@ -31,6 +31,15 @@ import ( ) // User3rdParty get user 3rdparty +// @Summary Get code repository user 3rdparty +// @security BasicAuth +// @Tags CodeRepository +// @Accept json +// @Produce json +// @Router /coderepos/{provider}/user3rdparty [get] +// @Param provider path string true "get user 3rdParty with provider" +// @Success 200 {object} types.GetCodeRepositoryUser3rdPartyResponse +// @Failure 500 {object} xerrors.ErrCode func (h *handlers) User3rdParty(c echo.Context) error { ctx := log.Logger.WithContext(c.Request().Context()) diff --git a/pkg/handlers/coderepos/handler.go b/pkg/handlers/coderepos/handler.go index e36f1c08..b70ddfc4 100644 --- a/pkg/handlers/coderepos/handler.go +++ b/pkg/handlers/coderepos/handler.go @@ -33,6 +33,8 @@ type Handlers interface { List(c echo.Context) error // ListOwner list all of the code repository owner ListOwners(c echo.Context) error + // ListBranches ... + ListBranches(c echo.Context) error // Resync resync all of the code repositories Resync(c echo.Context) error // Setup setup builder for code repository @@ -114,6 +116,7 @@ func (f factory) Initialize(e *echo.Echo) error { codereposGroup.GET("/:provider/user3rdparty", codeRepositoryHandler.User3rdParty) codereposGroup.GET("/:provider/resync", codeRepositoryHandler.Resync) codereposGroup.GET("/:provider/owners", codeRepositoryHandler.ListOwners) + codereposGroup.GET("/:id/branches", codeRepositoryHandler.ListBranches) codereposGroup.POST("/:id/setup-builder", codeRepositoryHandler.SetupBuilder) return nil } diff --git a/pkg/handlers/distribution/base/tags_list.go b/pkg/handlers/distribution/base/tags_list.go index 00ee203c..00e05d65 100644 --- a/pkg/handlers/distribution/base/tags_list.go +++ b/pkg/handlers/distribution/base/tags_list.go @@ -23,7 +23,7 @@ import ( "strconv" "strings" - "github.com/distribution/distribution/v3/reference" + "github.com/distribution/reference" "github.com/labstack/echo/v4" dtspecv1 "github.com/opencontainers/distribution-spec/specs-go/v1" "github.com/rs/zerolog/log" diff --git a/pkg/handlers/distribution/upload/upload_put.go b/pkg/handlers/distribution/upload/upload_put.go index 7242fcc2..c245bbec 100644 --- a/pkg/handlers/distribution/upload/upload_put.go +++ b/pkg/handlers/distribution/upload/upload_put.go @@ -22,7 +22,7 @@ import ( "strings" "time" - "github.com/distribution/distribution/v3/reference" + "github.com/distribution/reference" "github.com/labstack/echo/v4" "github.com/opencontainers/go-digest" "github.com/rs/zerolog/log" diff --git a/pkg/handlers/validators/reference_get.go b/pkg/handlers/validators/reference_get.go index b034c10c..e8a77ec9 100644 --- a/pkg/handlers/validators/reference_get.go +++ b/pkg/handlers/validators/reference_get.go @@ -18,7 +18,7 @@ import ( "net/http" "strings" - "github.com/distribution/distribution/v3/reference" + "github.com/distribution/reference" "github.com/labstack/echo/v4" "github.com/rs/zerolog/log" diff --git a/pkg/types/coderepos.go b/pkg/types/coderepos.go index 57f1bfc2..a4cf4482 100644 --- a/pkg/types/coderepos.go +++ b/pkg/types/coderepos.go @@ -57,6 +57,19 @@ type ListCodeRepositoryOwnerRequest struct { Name *string `json:"name,omitempty" query:"name" validate:"omitempty,min=1"` } +// ListCodeRepositoryBranchesRequest ... +type ListCodeRepositoryBranchesRequest struct { + ID int64 `json:"id" param:"id" validate:"required,number"` +} + +// CodeRepositoryBranchItem ... +type CodeRepositoryBranchItem struct { + ID int64 `json:"id" example:"1"` + Name string `json:"name" example:"main"` + CreatedAt string `json:"created_at" example:"2006-01-02 15:04:05"` + UpdatedAt string `json:"updated_at" example:"2006-01-02 15:04:05"` +} + // PostCodeRepositorySetupBuilder ... type PostCodeRepositorySetupBuilder struct { ID int64 `json:"id" param:"id" validate:"required,number"` diff --git a/pkg/types/user.go b/pkg/types/user.go index eb8e3555..ee9ef780 100644 --- a/pkg/types/user.go +++ b/pkg/types/user.go @@ -115,7 +115,7 @@ type PutUserSelfRequest struct { // ListCodeRepositoryProvidersResponse ... type ListCodeRepositoryProvidersResponse struct { - Provider enums.Provider `json:"providers" example:"github"` + Provider enums.Provider `json:"provider" example:"github"` } // GetCodeRepositoryResyncRequest ... diff --git a/pkg/utils/imagerefs/reference.go b/pkg/utils/imagerefs/reference.go index 7ae0669b..09dd49d9 100644 --- a/pkg/utils/imagerefs/reference.go +++ b/pkg/utils/imagerefs/reference.go @@ -19,7 +19,7 @@ import ( "fmt" "strings" - "github.com/distribution/distribution/v3/reference" + "github.com/distribution/reference" ) // Parse ... diff --git a/pkg/validators/validators.go b/pkg/validators/validators.go index f49c0785..fd0501ce 100644 --- a/pkg/validators/validators.go +++ b/pkg/validators/validators.go @@ -19,7 +19,7 @@ import ( "regexp" "strings" - "github.com/distribution/distribution/v3/reference" + "github.com/distribution/reference" "github.com/go-playground/validator" "github.com/labstack/echo/v4" "github.com/opencontainers/go-digest" diff --git a/web/package.json b/web/package.json index 4daa05ba..eafe2d07 100644 --- a/web/package.json +++ b/web/package.json @@ -14,7 +14,7 @@ "@headlessui/react": "^1.7.17", "@heroicons/react": "^2.0.18", "@tailwindcss/aspect-ratio": "^0.4.2", - "@tailwindcss/forms": "^0.5.5", + "@tailwindcss/forms": "^0.5.6", "@tailwindcss/line-clamp": "^0.4.4", "@tailwindcss/typography": "^0.5.9", "axios": "^1.5.0", @@ -40,7 +40,7 @@ "autoprefixer": "^10.4.15", "cssnano": "^6.0.1", "json-server": "^0.17.3", - "postcss": "^8.4.28", + "postcss": "^8.4.29", "tailwindcss": "^3.3.3", "typescript": "^5.2.2", "vite": "^4.4.9" diff --git a/web/src/App.tsx b/web/src/App.tsx index b4da2087..fe6238a9 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -31,14 +31,12 @@ import NamespaceDaemonTasks from "./pages/Namespace/DaemonTask"; import CodeRepositoryHome from './pages/CodeRepository'; import CodeRepositoryList from './pages/CodeRepository/List'; +import BuildersSetup from './pages/Builder/Setup'; + import { setupResponseInterceptor } from './utils/request' const localServer = process.env.NODE_ENV === "development" ? "http://127.0.0.1:3000" : ""; -function About() { - return

About

; -} - export default function App() { const navigate = useNavigate(); setupResponseInterceptor(navigate); @@ -77,7 +75,8 @@ export default function App() { } /> } /> - } /> + } /> + ); diff --git a/web/src/components/Menu/index.tsx b/web/src/components/Menu/index.tsx index 1aea02eb..8abae480 100644 --- a/web/src/components/Menu/index.tsx +++ b/web/src/components/Menu/index.tsx @@ -273,9 +273,10 @@ export default function ({ localServer, item, namespace, repository, tag }: { lo
{ - hotNamespaceList.map((ns, index) => { + hotNamespaceList.map((ns: INamespace, index: number) => { return ( { diff --git a/web/src/interfaces/index.ts b/web/src/interfaces/index.ts index d674c97e..51152b74 100644 --- a/web/src/interfaces/index.ts +++ b/web/src/interfaces/index.ts @@ -191,8 +191,20 @@ export interface ICodeRepositoryList { total: number; } +export interface ICodeRepositoryBranchItem { + id: number; + name: string; + created_at: string; + updated_at: string; +} + +export interface ICodeRepositoryBranchList { + items: ICodeRepositoryBranchItem[]; + total: number; +} + export interface ICodeRepositoryProviderItem { - providers: string; + provider: string; } export interface ICodeRepositoryProviderList { diff --git a/web/src/pages/Builder/Setup.tsx b/web/src/pages/Builder/Setup.tsx new file mode 100644 index 00000000..7d33920b --- /dev/null +++ b/web/src/pages/Builder/Setup.tsx @@ -0,0 +1,731 @@ +/** + * 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. + */ + +import _ from 'lodash'; +import axios from "axios"; +import { Listbox, Transition, Combobox } from '@headlessui/react'; +import { Helmet, HelmetProvider } from 'react-helmet-async'; +import { Fragment, useEffect, useRef, useState } from 'react'; +import { ChevronUpDownIcon, CheckIcon } from '@heroicons/react/20/solid'; +import { Link, useSearchParams, useParams, useNavigate } from 'react-router-dom'; + +import Settings from '../../Settings'; +import Header from '../../components/Header'; +import HeaderMenu from '../../components/Menu'; +import Toast from "../../components/Notification"; + +import { IHTTPError, INamespaceList, INamespace, IRepository, IRepositoryList, ICodeRepositoryOwnerItem, ICodeRepositoryItem, ICodeRepositoryProviderItem, ICodeRepositoryProviderList, ICodeRepositoryList, ICodeRepositoryOwnerList, ICodeRepositoryBranchItem, ICodeRepositoryBranchList } from '../../interfaces'; + +export default function ({ localServer }: { localServer: string }) { + const navigate = useNavigate(); + const [searchParams, setSearchParams] = useSearchParams(); + + useEffect(() => { + navigate(`?${searchParams.toString()}`); + }, [searchParams]); + + const [namespaceSearch, setNamespaceSearch] = useState(''); + const [namespaceList, setNamespaceList] = useState(); + const [namespaceSelected, setNamespaceSelected] = useState({ + name: searchParams.get('namespace') || "", + id: parseInt(searchParams.get('namespace_id') || "") || 0, + } as INamespace); + + useEffect(() => { + let url = localServer + `/api/v1/namespaces/?limit=5`; + if (namespaceSearch != null && namespaceSearch !== "") { + url += `&name=${namespaceSearch}`; + } + axios.get(url).then(response => { + if (response?.status === 200) { + const namespaceList = response.data as INamespaceList; + setNamespaceList(namespaceList.items); + } else { + const errorcode = response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + } + }).catch(error => { + const errorcode = error.response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + }); + }, [namespaceSearch]); + + const [repositorySearch, setRepositorySearch] = useState(''); + const [repositoryList, setRepositoryList] = useState(); + const [repositorySelected, setRepositorySelected] = useState({ + name: searchParams.get('repository') || "", + id: parseInt(searchParams.get('repository_id') || "") || 0, + } as IRepository); + + useEffect(() => { + if (namespaceSelected.name == undefined || namespaceSelected.name.length == 0) { + return; + } + let url = localServer + `/api/v1/namespaces/${namespaceSelected.name}/repositories/?limit=5`; + if (repositorySearch != null && repositorySearch !== "") { + url += `&name=${repositorySearch}`; + } + axios.get(url).then(response => { + if (response?.status === 200) { + const repositoryList = response.data as IRepositoryList; + setRepositoryList(repositoryList.items); + } else { + const errorcode = response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + } + }).catch(error => { + const errorcode = error.response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + }); + }, [namespaceSelected, repositorySearch]); + + const [codeRepositoryProviderList, setCodeRepositoryProviderList] = useState(); + const [codeRepositoryProviderSelected, setCodeRepositoryProviderSelected] = useState({ + provider: searchParams.get('provider') || "", + } as ICodeRepositoryProviderItem); + + useEffect(() => { + let url = localServer + `/api/v1/coderepos/providers`; + axios.get(url).then(response => { + if (response?.status === 200) { + const providerList = response.data as ICodeRepositoryProviderList; + setCodeRepositoryProviderList(providerList.items); + } else { + const errorcode = response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + } + }).catch(error => { + const errorcode = error.response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + }); + }, []); + + const [codeRepositoryOwnerSearch, setCodeRepositoryOwnerSearch] = useState(''); + const [codeRepositoryOwnerList, setCodeRepositoryOwnerList] = useState(); + const [codeRepositoryOwnerFilteredList, setCodeRepositoryOwnerFilteredList] = useState(); + const [codeRepositoryOwnerSelected, setCodeRepositoryOwnerSelected] = useState({ + owner: searchParams.get('code_repository_owner') || '', + id: parseInt(searchParams.get('code_repository_owner_id') || "") || 0, + } as ICodeRepositoryOwnerItem); + + useEffect(() => { + if (codeRepositoryProviderSelected.provider == undefined || codeRepositoryProviderSelected.provider == "") { + return; + } + axios.get(`${localServer}/api/v1/coderepos/${codeRepositoryProviderSelected.provider}/owners`).then(response => { + if (response.status == 200) { + const data = response.data as ICodeRepositoryOwnerList; + setCodeRepositoryOwnerList(_.orderBy(data.items, ['is_org'])); + setCodeRepositoryOwnerFilteredList(_.orderBy(data.items, ['is_org'])); + } else { + const errorcode = response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + } + }).catch(error => { + const errorcode = error.response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + }); + }, [codeRepositoryProviderSelected]); + + useEffect(() => { + if (codeRepositoryOwnerList?.length == undefined || codeRepositoryOwnerList?.length == 0) { + return; + } + if (codeRepositoryOwnerSearch == '') { + setCodeRepositoryOwnerFilteredList(codeRepositoryOwnerList); + return; + } + let result = []; + for (let i = 0; i < (codeRepositoryOwnerList?.length || 0); i++) { + if (codeRepositoryOwnerList[i].owner.toLowerCase().includes(codeRepositoryOwnerSearch.toLocaleLowerCase())) { + result.push(codeRepositoryOwnerList[i]) + } + } + setCodeRepositoryOwnerFilteredList(result); + }, [codeRepositoryOwnerSearch]) + + const [codeRepositorySearch, setCodeRepositorySearch] = useState(''); + const [codeRepositoryList, setCodeRepositoryList] = useState(); + const [codeRepositorySelected, setCodeRepositorySelected] = useState({ + name: searchParams.get('code_repository_name') || '', + id: parseInt(searchParams.get('code_repository_id') || "") || 0, + } as ICodeRepositoryItem); + + useEffect(() => { + if (codeRepositoryProviderSelected.provider == undefined || codeRepositoryProviderSelected.provider == "") { + return; + } + if (codeRepositoryOwnerSelected.owner == undefined || codeRepositoryOwnerSelected.owner == "") { + return; + } + let url = `${localServer}/api/v1/coderepos/${codeRepositoryProviderSelected.provider}?owner=${codeRepositoryOwnerSelected.owner}&limit=5`; + if (codeRepositorySearch != null && codeRepositorySearch !== "") { + url += `&name=${codeRepositorySearch}`; + } + axios.get(url).then(response => { + if (response.status == 200) { + const data = response.data as ICodeRepositoryList; + setCodeRepositoryList(data.items); + } else { + const errorcode = response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + } + }).catch(error => { + const errorcode = error.response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + }); + }, [codeRepositoryOwnerSelected, codeRepositoryProviderSelected, codeRepositorySearch]); + + const [codeRepositoryBranchSearch, setCodeRepositoryBranchSearch] = useState(''); + const [codeRepositoryBranchList, setCodeRepositoryBranchList] = useState(); + const [codeRepositoryBranchFilteredList, setCodeRepositoryBranchFilteredList] = useState(); + const [codeRepositoryBranchSelected, setCodeRepositoryBranchSelected] = useState({ + name: searchParams.get('code_repository_branch_name') || '', + id: parseInt(searchParams.get('code_repository_branch_id') || "") || 0, + } as ICodeRepositoryBranchItem); + + useEffect(() => { + if (codeRepositorySelected.id == undefined || codeRepositorySelected.id == 0) { + return; + } + let url = `${localServer}/api/v1/coderepos/${codeRepositorySelected.id}/branches`; + axios.get(url).then(response => { + if (response.status == 200) { + const data = response.data as ICodeRepositoryBranchList; + setCodeRepositoryBranchList(data.items); + setCodeRepositoryBranchFilteredList(data.items); + } else { + const errorcode = response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + } + }).catch(error => { + const errorcode = error.response.data as IHTTPError; + Toast({ level: "warning", title: errorcode.title, message: errorcode.description }); + }); + }, [codeRepositorySelected]); + + useEffect(() => { + if (codeRepositoryBranchList?.length == undefined || codeRepositoryBranchList?.length == 0) { + return; + } + if (codeRepositoryBranchSearch == '') { + setCodeRepositoryBranchFilteredList(codeRepositoryBranchList); + } + let result = []; + for (let i = 0; i < (codeRepositoryBranchList?.length || 0); i++) { + if (codeRepositoryBranchList[i].name.toLowerCase().includes(codeRepositoryBranchSearch.toLocaleLowerCase())) { + result.push(codeRepositoryBranchList[i]) + } + } + setCodeRepositoryBranchFilteredList(result); + }, [codeRepositoryBranchSearch]); + + const [submodule, setSubmodule] = useState(false); + const [depth, setDepth] = useState(0); + + return ( + + + + sigma - Code Repositories + + +
+ +
+ {/* part 1 begin */} +
+
+
+ {/* part 1 end */} + {/* part 2 begin */} +
+
+

OCI Repository

+

Builder will push the artifact to this repository.

+
+
+ +
+ { + setSearchParams({ + ...Object.fromEntries(searchParams.entries()), + namespace: namespace.name, + namespace_id: namespace.id.toString(), + repository: '', + repository_id: '', + }); + setRepositorySelected({} as IRepository); // clear the repo selected + setNamespaceSelected(namespace); + }}> +
+
+ namespace.name} + onChange={(event) => { + setNamespaceSearch(event.target.value); + }} + /> + + +
+ setNamespaceSearch('')} + > + + { + namespaceList?.length === 0 ? ( +
+ Nothing found. +
+ ) : ( + namespaceList?.map(namespace => ( + + `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-gray-200 text-gray-800' : 'text-gray-900' + }` + } + value={namespace} + > + + {namespace.name} + + + )) + ) + } +
+
+
+
+
+
+
+ +
+ { + setSearchParams({ + ...Object.fromEntries(searchParams.entries()), + repository: repo.name, + repository_id: repo.id.toString(), + }); + setRepositorySelected(repo); + }}> +
+
+ { + if (namespaceSelected.name != undefined && repository.name != undefined) { + return repository.name.substring(namespaceSelected.name.length + 1) + } + return ""; + }} + onChange={(event) => { + setRepositorySearch(event.target.value); + }} + /> + + +
+ setRepositorySearch('')} + > + + { + repositoryList?.length === 0 ? ( +
+ Nothing found. +
+ ) : ( + repositoryList?.map(repository => ( + + `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-gray-200 text-gray-800' : 'text-gray-900' + }` + } + value={repository} + > + + {repository.name.substring(namespaceSelected.name.length + 1)} + + + )) + ) + } +
+
+
+
+
+
+
+
+
+

Code Repository

+

Builder will clone source code from here.

+
+
+ +
+ { + setSearchParams({ + ...Object.fromEntries(searchParams.entries()), + provider: provider.provider, + }); + setCodeRepositoryOwnerSelected({} as ICodeRepositoryOwnerItem); // clear the selected + setCodeRepositorySelected({} as ICodeRepositoryItem); + setCodeRepositoryBranchSelected({} as ICodeRepositoryBranchItem); + setCodeRepositoryProviderSelected(provider); + }}> +
+
+ provider.provider} + onChange={(event) => { }} + /> + + +
+ + + { + codeRepositoryProviderList?.length === 0 ? ( +
+ Nothing found. +
+ ) : ( + codeRepositoryProviderList?.map(provider => ( + + `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-gray-200 text-gray-800' : 'text-gray-900' + }` + } + value={provider} + > + + {provider.provider} + + + )) + ) + } +
+
+
+
+
+
+
+ +
+ { + setSearchParams({ + ...Object.fromEntries(searchParams.entries()), + code_repository_owner: owner.owner, + code_repository_owner_id: owner.id.toString(), + }); + setCodeRepositorySelected({} as ICodeRepositoryItem); + setCodeRepositoryBranchSelected({} as ICodeRepositoryBranchItem); + setCodeRepositoryOwnerSelected(owner); + }}> +
+
+ owner.owner} + onChange={(event) => { + setCodeRepositoryOwnerSearch(event.target.value); + }} + /> + + +
+ setCodeRepositoryOwnerSearch('')} + > + + { + codeRepositoryOwnerFilteredList?.length === 0 ? ( +
+ Nothing found. +
+ ) : ( + codeRepositoryOwnerFilteredList?.map(owner => ( + + `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-gray-200 text-gray-800' : 'text-gray-900' + }` + } + value={owner} + > + + {owner.owner} + + + )) + ) + } +
+
+
+
+
+
+
+ +
+ { + setSearchParams({ + ...Object.fromEntries(searchParams.entries()), + code_repository_name: cr.name, + code_repository_id: cr.id.toString(), + }); + setCodeRepositoryBranchSelected({} as ICodeRepositoryBranchItem); + setCodeRepositorySelected(cr); + }}> +
+
+ cr.name} + onChange={(event) => { + setCodeRepositorySearch(event.target.value); + }} + /> + + +
+ setCodeRepositorySearch('')} + > + + { + codeRepositoryList?.length === 0 ? ( +
+ Nothing found. +
+ ) : ( + codeRepositoryList?.map(cr => ( + + `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-gray-200 text-gray-800' : 'text-gray-900' + }` + } + value={cr} + > + + {cr.name} {cr.clone_url} + + + )) + ) + } +
+
+
+
+
+
+
+ +
+ { + setSearchParams({ + ...Object.fromEntries(searchParams.entries()), + code_repository_branch_name: branch.name, + code_repository_branch_id: branch.id.toString(), + }); + setCodeRepositoryBranchSelected(branch); + }}> +
+
+ branch.name} + onChange={(event) => { + setCodeRepositoryBranchSearch(event.target.value); + }} + /> + + +
+ setCodeRepositoryBranchSearch('')} + > + + { + codeRepositoryBranchFilteredList?.length === 0 ? ( +
+ Nothing found. +
+ ) : ( + codeRepositoryBranchFilteredList?.map(branch => ( + + `relative cursor-pointer select-none py-2 pl-4 pr-4 ${active ? 'bg-gray-200 text-gray-800' : 'text-gray-900' + }` + } + value={branch} + > + + {branch.name} + + + )) + ) + } +
+
+
+
+
+
+
+
+
+ +
+ +
+
+
+ +
+ setDepth(Number.isNaN(parseInt(e.target.value)) ? "" : parseInt(e.target.value))} + /> +
+
+
+
+
+ {/* part 2 end */} + {/* part 3 begin */} +
+
+
+
+
+ + +
+
+
+ {/* part 3 end */} +
+
+
+ ); +} diff --git a/web/src/pages/CodeRepository/List.tsx b/web/src/pages/CodeRepository/List.tsx index 54eab0c2..eac6eb5d 100644 --- a/web/src/pages/CodeRepository/List.tsx +++ b/web/src/pages/CodeRepository/List.tsx @@ -17,14 +17,11 @@ import _ from 'lodash'; import axios from 'axios'; import dayjs from 'dayjs'; -import { useParams, Link } from 'react-router-dom'; -import { Fragment, useEffect, useRef, useState } from 'react'; import { Listbox, Transition } from '@headlessui/react'; +import { useParams, useNavigate } from 'react-router-dom'; import { Helmet, HelmetProvider } from 'react-helmet-async'; import { ChevronUpDownIcon } from '@heroicons/react/20/solid'; -import { Dialog, Menu } from '@headlessui/react'; -import { EllipsisVerticalIcon } from '@heroicons/react/20/solid'; -import { ExclamationTriangleIcon } from '@heroicons/react/24/outline' +import { Fragment, useEffect, useRef, useState } from 'react'; import Settings from '../../Settings'; import HeaderMenu from '../../components/Menu'; @@ -152,7 +149,7 @@ export default function ({ localServer }: { localServer: string }) { return; } axios.get(`${localServer}/api/v1/coderepos/${provider}/resync`).then(response => { - if (response.status == 200) { + if (response.status == 202) { setTimeout(() => { setRefresh({}); }, 200) Toast({ level: "success", title: "Code Repository is synchronizing", message: "" }); } else { @@ -305,7 +302,7 @@ export default function ({ localServer }: { localServer: string }) { { repositories?.map((repository, index) => { return ( - + ); }) } @@ -325,12 +322,14 @@ export default function ({ localServer }: { localServer: string }) { ) } -function TableItem({ localServer, index, repository }: { localServer: string, index: number, repository: ICodeRepositoryItem }) { +// TODO: if user have no namespace setup button just display a notification +function TableItem({ repository }: { repository: ICodeRepositoryItem }) { + const navigate = useNavigate(); return ( { - // navigate(`/namespaces/${namespace.name}/repositories`); + window.open(repository.clone_url, "_blank"); }} >
@@ -345,7 +344,11 @@ function TableItem({ localServer, index, repository }: { localServer: string, in {repository.oci_repo_count} - + { + navigate("/builders/setup") + }} + > Setup diff --git a/web/src/pages/CodeRepository/index.tsx b/web/src/pages/CodeRepository/index.tsx index 21417f41..c09929ec 100644 --- a/web/src/pages/CodeRepository/index.tsx +++ b/web/src/pages/CodeRepository/index.tsx @@ -66,7 +66,7 @@ export default function ({ localServer }: { localServer: string }) { const hasProvider = (provider: string) => { if (providers?.length !== undefined && providers?.length > 0) { for (let i = 0; i < providers.length; i++) { - if (providers[i].providers === provider) { + if (providers[i].provider === provider) { return true; } } diff --git a/web/yarn.lock b/web/yarn.lock index 241b72f5..f5cec90c 100644 --- a/web/yarn.lock +++ b/web/yarn.lock @@ -340,10 +340,10 @@ resolved "https://registry.yarnpkg.com/@tailwindcss/aspect-ratio/-/aspect-ratio-0.4.2.tgz#9ffd52fee8e3c8b20623ff0dcb29e5c21fb0a9ba" integrity sha512-8QPrypskfBa7QIMuKHg2TA7BqES6vhBrDLOv8Unb6FcFyd3TjKbc6lcmb9UPQHxfl24sXoJ41ux/H7qQQvfaSQ== -"@tailwindcss/forms@^0.5.5": - version "0.5.5" - resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.5.tgz#2965ee74159a16b5ef012d5eddae20c9b48aa49c" - integrity sha512-03sXK1DcPt44GZ0Yg6AcAfQln89IKdbE79g2OwoKqBm1ukaadLO2AH3EiB3mXHeQnxa3tzm7eE0x7INXSjbuug== +"@tailwindcss/forms@^0.5.6": + version "0.5.6" + resolved "https://registry.yarnpkg.com/@tailwindcss/forms/-/forms-0.5.6.tgz#29c6c2b032b363e0c5110efed1499867f6d7e868" + integrity sha512-Fw+2BJ0tmAwK/w01tEFL5TiaJBX1NLT1/YbWgvm7ws3Qcn11kiXxzNTEQDMs5V3mQemhB56l3u0i9dwdzSQldA== dependencies: mini-svg-data-uri "^1.2.3" @@ -3687,10 +3687,10 @@ postcss@^8.4.23, postcss@^8.4.27: picocolors "^1.0.0" source-map-js "^1.0.2" -postcss@^8.4.28: - version "8.4.28" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.28.tgz#c6cc681ed00109072816e1557f889ef51cf950a5" - integrity sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw== +postcss@^8.4.29: + version "8.4.29" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.29.tgz#33bc121cf3b3688d4ddef50be869b2a54185a1dd" + integrity sha512-cbI+jaqIeu/VGqXEarWkRCCffhjgXc0qjBtXpqJhTBohMUjUQnbBr0xqX3vEKudc4iviTewcJo5ajcec5+wdJw== dependencies: nanoid "^3.3.6" picocolors "^1.0.0"