mirror of https://github.com/harness/drone.git
feat: Image Upload (Backend) (#651)
parent
1220faf659
commit
23b9117302
|
@ -0,0 +1,100 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/app/auth/authz"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/blob"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
const (
|
||||
imageContentType = "image"
|
||||
MaxFileSize = 5 << 20 // 5 MB file limit set in Handler
|
||||
fileBucketPathFmt = "uploads/%d/%s"
|
||||
peekBytes = 512
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
authorizer authz.Authorizer
|
||||
repoStore store.RepoStore
|
||||
blobStore blob.Store
|
||||
}
|
||||
|
||||
func NewController(authorizer authz.Authorizer,
|
||||
repoStore store.RepoStore,
|
||||
blobStore blob.Store,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
authorizer: authorizer,
|
||||
repoStore: repoStore,
|
||||
blobStore: blobStore,
|
||||
}
|
||||
}
|
||||
func (c *Controller) getRepoCheckAccess(ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
reqPermission enum.Permission,
|
||||
orPublic bool,
|
||||
) (*types.Repository, error) {
|
||||
if repoRef == "" {
|
||||
return nil, usererror.BadRequest("A valid repository reference must be provided.")
|
||||
}
|
||||
|
||||
repo, err := c.repoStore.FindByRef(ctx, repoRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find repo: %w", err)
|
||||
}
|
||||
|
||||
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, orPublic); err != nil {
|
||||
return nil, fmt.Errorf("failed to verify authorization: %w", err)
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (c *Controller) ensureTypeImgAndGetExtn(file *bufio.Reader) (string, error) {
|
||||
buf, err := file.Peek(peekBytes)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to read file: %w", err)
|
||||
}
|
||||
|
||||
detectedContentType := http.DetectContentType(buf)
|
||||
if !strings.HasPrefix(detectedContentType, imageContentType) {
|
||||
return "", usererror.BadRequestf("only image files are supported, uploaded file is of type %s", detectedContentType)
|
||||
}
|
||||
|
||||
contentTypeSlice := strings.Split(detectedContentType, "/")
|
||||
if len(contentTypeSlice) < 2 {
|
||||
return "", fmt.Errorf("failed to parse content type %s", detectedContentType)
|
||||
}
|
||||
extn := contentTypeSlice[1]
|
||||
return extn, nil
|
||||
}
|
||||
|
||||
func getFileBucketPath(repoID int64, fileName string) string {
|
||||
return fmt.Sprintf(fileBucketPathFmt, repoID, fileName)
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/blob"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
func (c *Controller) Download(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
filePath string,
|
||||
) (string, io.ReadCloser, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, true)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to acquire access to repo: %w", err)
|
||||
}
|
||||
|
||||
fileBucketPath := getFileBucketPath(repo.ID, filePath)
|
||||
|
||||
signedURL, err := c.blobStore.GetSignedURL(fileBucketPath)
|
||||
if err != nil && !errors.Is(err, blob.ErrNotSupported) {
|
||||
return "", nil, fmt.Errorf("failed to get signed URL: %w", err)
|
||||
}
|
||||
|
||||
if signedURL != "" {
|
||||
return signedURL, nil, nil
|
||||
}
|
||||
|
||||
file, err := c.blobStore.Download(ctx, fileBucketPath)
|
||||
if err != nil {
|
||||
return "", nil, fmt.Errorf("failed to download file from blobstore: %w", err)
|
||||
}
|
||||
|
||||
return "", file, nil
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
// Result contains the information about the upload.
|
||||
type Result struct {
|
||||
FilePath string `json:"file_path"`
|
||||
}
|
||||
|
||||
const (
|
||||
fileNameFmt = "%s.%s"
|
||||
)
|
||||
|
||||
func (c *Controller) Upload(ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
file io.Reader,
|
||||
) (*Result, error) {
|
||||
// Permission check to see if the user in request has access to the repo.
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView, false)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to repo: %w", err)
|
||||
}
|
||||
|
||||
if file == nil {
|
||||
return nil, usererror.BadRequest("no file provided")
|
||||
}
|
||||
bufReader := bufio.NewReader(file)
|
||||
// Check if the file is an image
|
||||
extn, err := c.ensureTypeImgAndGetExtn(bufReader)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to determine file type: %w", err)
|
||||
}
|
||||
|
||||
uid := uuid.New().String()
|
||||
fileName := fmt.Sprintf(fileNameFmt, uid, extn)
|
||||
|
||||
fileBucketPath := getFileBucketPath(repo.ID, fileName)
|
||||
err = c.blobStore.Upload(ctx, bufReader, fileBucketPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upload file: %w", err)
|
||||
}
|
||||
return &Result{
|
||||
FilePath: fileName,
|
||||
}, nil
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/app/auth/authz"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/blob"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// WireSet provides a wire set for this package.
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideController,
|
||||
)
|
||||
|
||||
func ProvideController(
|
||||
authorizer authz.Authorizer,
|
||||
repoStore store.RepoStore,
|
||||
blobStore blob.Store,
|
||||
) *Controller {
|
||||
return NewController(authorizer, repoStore, blobStore)
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/upload"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func HandleDownoad(controller *upload.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
filename, err := request.GetRemainderFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
signedFileURL, file, err := controller.Download(ctx, session, repoRef, filename)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
if file != nil {
|
||||
render.Reader(ctx, w, http.StatusOK, file)
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
log.Ctx(ctx).Error().Err(err).Msg("failed to close file after rendering")
|
||||
}
|
||||
return
|
||||
}
|
||||
http.Redirect(
|
||||
w,
|
||||
r,
|
||||
signedFileURL,
|
||||
http.StatusTemporaryRedirect,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package upload
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/upload"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
func HandleUpload(controller *upload.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
r.Body = http.MaxBytesReader(w, r.Body, upload.MaxFileSize)
|
||||
|
||||
res, err := controller.Upload(ctx, session, repoRef, r.Body)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
render.JSON(w, http.StatusOK, res)
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ import (
|
|||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/services/webhook"
|
||||
"github.com/harness/gitness/blob"
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/store"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
@ -32,6 +33,7 @@ func Translate(err error) *Error {
|
|||
rError *Error
|
||||
checkError *check.ValidationError
|
||||
gitrpcError *gitrpc.Error
|
||||
maxBytesErr *http.MaxBytesError
|
||||
)
|
||||
|
||||
// TODO: Improve performance of checking multiple errors with errors.Is
|
||||
|
@ -67,6 +69,12 @@ func Translate(err error) *Error {
|
|||
case errors.Is(err, store.ErrSpaceWithChildsCantBeDeleted):
|
||||
return ErrSpaceWithChildsCantBeDeleted
|
||||
|
||||
// upload errors
|
||||
case errors.Is(err, blob.ErrNotFound):
|
||||
return ErrNotFound
|
||||
case errors.As(err, &maxBytesErr):
|
||||
return ErrRequestTooLargeF("The request is too large. maximum allowed size is %d bytes", maxBytesErr.Limit)
|
||||
|
||||
// gitrpc errors
|
||||
case errors.As(err, &gitrpcError):
|
||||
return NewWithPayload(httpStatusCode(
|
||||
|
|
|
@ -121,6 +121,10 @@ func BadRequestf(format string, args ...any) *Error {
|
|||
return Newf(http.StatusBadRequest, format, args...)
|
||||
}
|
||||
|
||||
func ErrRequestTooLargeF(format string, args ...any) *Error {
|
||||
return Newf(http.StatusRequestEntityTooLarge, format, args...)
|
||||
}
|
||||
|
||||
// BadRequestWithPayload returns a new user facing bad request error with payload.
|
||||
func BadRequestWithPayload(message string, values ...map[string]any) *Error {
|
||||
return NewWithPayload(http.StatusBadRequest, message, values...)
|
||||
|
|
|
@ -34,6 +34,7 @@ import (
|
|||
"github.com/harness/gitness/app/api/controller/system"
|
||||
"github.com/harness/gitness/app/api/controller/template"
|
||||
"github.com/harness/gitness/app/api/controller/trigger"
|
||||
"github.com/harness/gitness/app/api/controller/upload"
|
||||
"github.com/harness/gitness/app/api/controller/user"
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/api/handler/account"
|
||||
|
@ -54,6 +55,7 @@ import (
|
|||
handlersystem "github.com/harness/gitness/app/api/handler/system"
|
||||
handlertemplate "github.com/harness/gitness/app/api/handler/template"
|
||||
handlertrigger "github.com/harness/gitness/app/api/handler/trigger"
|
||||
handlerupload "github.com/harness/gitness/app/api/handler/upload"
|
||||
handleruser "github.com/harness/gitness/app/api/handler/user"
|
||||
"github.com/harness/gitness/app/api/handler/users"
|
||||
handlerwebhook "github.com/harness/gitness/app/api/handler/webhook"
|
||||
|
@ -107,6 +109,7 @@ func NewAPIHandler(
|
|||
principalCtrl principal.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
sysCtrl *system.Controller,
|
||||
uploadCtrl *upload.Controller,
|
||||
) APIHandler {
|
||||
// Use go-chi router for inner routing.
|
||||
r := chi.NewRouter()
|
||||
|
@ -131,7 +134,7 @@ func NewAPIHandler(
|
|||
r.Route("/v1", func(r chi.Router) {
|
||||
setupRoutesV1(r, config, repoCtrl, executionCtrl, triggerCtrl, logCtrl, pipelineCtrl,
|
||||
connectorCtrl, templateCtrl, pluginCtrl, secretCtrl, spaceCtrl, pullreqCtrl,
|
||||
webhookCtrl, githookCtrl, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl)
|
||||
webhookCtrl, githookCtrl, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl, uploadCtrl)
|
||||
})
|
||||
|
||||
// wrap router in terminatedPath encoder.
|
||||
|
@ -171,9 +174,11 @@ func setupRoutesV1(r chi.Router,
|
|||
principalCtrl principal.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
sysCtrl *system.Controller,
|
||||
uploadCtrl *upload.Controller,
|
||||
) {
|
||||
setupSpaces(r, spaceCtrl)
|
||||
setupRepos(r, repoCtrl, pipelineCtrl, executionCtrl, triggerCtrl, logCtrl, pullreqCtrl, webhookCtrl, checkCtrl)
|
||||
setupRepos(r, repoCtrl, pipelineCtrl, executionCtrl, triggerCtrl, logCtrl, pullreqCtrl, webhookCtrl, checkCtrl,
|
||||
uploadCtrl)
|
||||
setupConnectors(r, connectorCtrl)
|
||||
setupTemplates(r, templateCtrl)
|
||||
setupSecrets(r, secretCtrl)
|
||||
|
@ -233,6 +238,7 @@ func setupRepos(r chi.Router,
|
|||
pullreqCtrl *pullreq.Controller,
|
||||
webhookCtrl *webhook.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
uploadCtrl *upload.Controller,
|
||||
) {
|
||||
r.Route("/repos", func(r chi.Router) {
|
||||
// Create takes path and parentId via body, not uri
|
||||
|
@ -315,10 +321,19 @@ func setupRepos(r chi.Router,
|
|||
setupPipelines(r, repoCtrl, pipelineCtrl, executionCtrl, triggerCtrl, logCtrl)
|
||||
|
||||
SetupChecks(r, checkCtrl)
|
||||
|
||||
setupUploads(r, uploadCtrl)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func setupUploads(r chi.Router, uploadCtrl *upload.Controller) {
|
||||
r.Route("/uploads", func(r chi.Router) {
|
||||
r.Post("/", handlerupload.HandleUpload(uploadCtrl))
|
||||
r.Get("/*", handlerupload.HandleDownoad(uploadCtrl))
|
||||
})
|
||||
}
|
||||
|
||||
func setupPipelines(
|
||||
r chi.Router,
|
||||
repoCtrl *repo.Controller,
|
||||
|
|
|
@ -33,6 +33,7 @@ import (
|
|||
"github.com/harness/gitness/app/api/controller/system"
|
||||
"github.com/harness/gitness/app/api/controller/template"
|
||||
"github.com/harness/gitness/app/api/controller/trigger"
|
||||
"github.com/harness/gitness/app/api/controller/upload"
|
||||
"github.com/harness/gitness/app/api/controller/user"
|
||||
"github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/auth/authn"
|
||||
|
@ -115,10 +116,11 @@ func ProvideAPIHandler(
|
|||
principalCtrl principal.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
sysCtrl *system.Controller,
|
||||
blobCtrl *upload.Controller,
|
||||
) APIHandler {
|
||||
return NewAPIHandler(config, authenticator, repoCtrl, executionCtrl, logCtrl, spaceCtrl, pipelineCtrl,
|
||||
secretCtrl, triggerCtrl, connectorCtrl, templateCtrl, pluginCtrl, pullreqCtrl, webhookCtrl,
|
||||
githookCtrl, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl)
|
||||
githookCtrl, saCtrl, userCtrl, principalCtrl, checkCtrl, sysCtrl, blobCtrl)
|
||||
}
|
||||
|
||||
func ProvideWebHandler(config *types.Config) WebHandler {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package blob
|
||||
|
||||
type Provider string
|
||||
|
||||
const (
|
||||
ProviderGCS Provider = "gcs"
|
||||
ProviderFileSystem Provider = "filesystem"
|
||||
)
|
||||
|
||||
type Config struct {
|
||||
Provider Provider
|
||||
Bucket string
|
||||
KeyPath string
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
const (
|
||||
fileDiskPathFmt = "%s/%s"
|
||||
)
|
||||
|
||||
type FileSystemStore struct {
|
||||
basePath string
|
||||
}
|
||||
|
||||
func NewFileSystemStore(cfg Config) (Store, error) {
|
||||
return &FileSystemStore{
|
||||
basePath: cfg.Bucket,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c FileSystemStore) Upload(ctx context.Context,
|
||||
file io.Reader,
|
||||
filePath string,
|
||||
) error {
|
||||
fileDiskPath := fmt.Sprintf(fileDiskPathFmt, c.basePath, filePath)
|
||||
|
||||
dir, _ := path.Split(fileDiskPath)
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
err = os.MkdirAll(dir, os.ModeDir|os.ModePerm)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create parent directory for the file: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
destinationFile, err := os.Create(fileDiskPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create file: %w", err)
|
||||
}
|
||||
defer func() {
|
||||
cErr := destinationFile.Close()
|
||||
if cErr != nil {
|
||||
log.Ctx(ctx).Err(cErr).
|
||||
Msgf("failed to close destination file '%s' in directory '%s'", filePath, c.basePath)
|
||||
}
|
||||
}()
|
||||
|
||||
if _, err := io.Copy(destinationFile, file); err != nil {
|
||||
// Remove the file if it was created.
|
||||
removeErr := os.Remove(fileDiskPath)
|
||||
if removeErr != nil {
|
||||
return fmt.Errorf("failed to remove file: %w", removeErr)
|
||||
}
|
||||
return fmt.Errorf("failed to write file to filesystem: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c FileSystemStore) GetSignedURL(filePath string) (string, error) {
|
||||
return "", ErrNotSupported
|
||||
}
|
||||
|
||||
func (c *FileSystemStore) Download(ctx context.Context, filePath string) (io.ReadCloser, error) {
|
||||
fileDiskPath := fmt.Sprintf(fileDiskPathFmt, c.basePath, filePath)
|
||||
|
||||
file, err := os.Open(fileDiskPath)
|
||||
if os.IsNotExist(err) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
return io.ReadCloser(file), nil
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"cloud.google.com/go/storage"
|
||||
"github.com/rs/zerolog/log"
|
||||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
type GCSStore struct {
|
||||
// Bucket is the name of the GCS bucket to use.
|
||||
bucket string
|
||||
client *storage.Client
|
||||
}
|
||||
|
||||
func NewGCSStore(cfg Config) (Store, error) {
|
||||
// Use service account [Development and Non-GCP environments]
|
||||
if cfg.KeyPath != "" {
|
||||
client, err := storage.NewClient(context.Background(), option.WithCredentialsFile(cfg.KeyPath))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create GCS client with service account key: %w", err)
|
||||
}
|
||||
return &GCSStore{
|
||||
bucket: cfg.Bucket,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Use workload identity default credentials (GKE environment)
|
||||
client, err := storage.NewClient(context.Background())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create GCS client with workload identity or default credentials: %w", err)
|
||||
}
|
||||
return &GCSStore{
|
||||
bucket: cfg.Bucket,
|
||||
client: client,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *GCSStore) Upload(ctx context.Context, file io.Reader, filePath string) error {
|
||||
wc := c.client.Bucket(c.bucket).Object(filePath).NewWriter(ctx)
|
||||
defer func() {
|
||||
cErr := wc.Close()
|
||||
if cErr != nil {
|
||||
log.Ctx(ctx).Err(cErr).
|
||||
Msgf("failed to close gcs blob writer for file '%s' in bucket '%s'", filePath, c.bucket)
|
||||
}
|
||||
}()
|
||||
if _, err := io.Copy(wc, file); err != nil {
|
||||
// Remove the file if it was created.
|
||||
deleteErr := c.client.Bucket(c.bucket).Object(filePath).Delete(ctx)
|
||||
if deleteErr != nil {
|
||||
return fmt.Errorf("failed to delete file: %s from bucket: %s %w", filePath, c.bucket, deleteErr)
|
||||
}
|
||||
|
||||
return fmt.Errorf("failed to write file to GCS: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *GCSStore) GetSignedURL(filePath string) (string, error) {
|
||||
signedURL, err := c.client.Bucket(c.bucket).SignedURL(filePath, &storage.SignedURLOptions{
|
||||
Method: http.MethodGet,
|
||||
Expires: time.Now().Add(1 * time.Hour),
|
||||
})
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to create signed URL for file: %s %w", filePath, err)
|
||||
}
|
||||
return signedURL, nil
|
||||
}
|
||||
func (c *GCSStore) Download(ctx context.Context, filePath string) (io.ReadCloser, error) {
|
||||
return nil, fmt.Errorf("not implemented")
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package blob
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"io"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNotFound = errors.New("resource not found")
|
||||
ErrNotSupported = errors.New("not supported")
|
||||
)
|
||||
|
||||
type Store interface {
|
||||
// Upload uploads a file to the blob store.
|
||||
Upload(ctx context.Context, file io.Reader, filePath string) error
|
||||
|
||||
// GetSignedURL returns the URL for a file in the blob store.
|
||||
GetSignedURL(filePath string) (string, error)
|
||||
|
||||
// Download returns a reader for a file in the blob store.
|
||||
Download(ctx context.Context, filePath string) (io.ReadCloser, error)
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright 2023 Harness, Inc.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package blob
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideStore,
|
||||
)
|
||||
|
||||
func ProvideStore(config Config) (Store, error) {
|
||||
switch config.Provider {
|
||||
case ProviderFileSystem:
|
||||
return NewFileSystemStore(config)
|
||||
case ProviderGCS:
|
||||
return NewGCSStore(config)
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid blob store provider: %s", config.Provider)
|
||||
}
|
||||
}
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/harness/gitness/app/services/cleanup"
|
||||
"github.com/harness/gitness/app/services/trigger"
|
||||
"github.com/harness/gitness/app/services/webhook"
|
||||
"github.com/harness/gitness/blob"
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/gitrpc/server"
|
||||
|
@ -40,8 +41,10 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
schemeHTTP = "http"
|
||||
schemeHTTPS = "https"
|
||||
schemeHTTP = "http"
|
||||
schemeHTTPS = "https"
|
||||
gitnessHomeDir = ".gitness"
|
||||
blobDir = "blob"
|
||||
)
|
||||
|
||||
// LoadConfig returns the system configuration from the
|
||||
|
@ -207,6 +210,25 @@ func ProvideDatabaseConfig(config *types.Config) database.Config {
|
|||
}
|
||||
}
|
||||
|
||||
// ProvideBlobStoreConfig loads the blob store config from the main config.
|
||||
func ProvideBlobStoreConfig(config *types.Config) (blob.Config, error) {
|
||||
// Prefix home directory in case of filesystem blobstore
|
||||
if config.BlobStore.Provider == blob.ProviderFileSystem && config.BlobStore.Bucket == "" {
|
||||
var homedir string
|
||||
homedir, err := os.UserHomeDir()
|
||||
if err != nil {
|
||||
return blob.Config{}, err
|
||||
}
|
||||
|
||||
config.BlobStore.Bucket = filepath.Join(homedir, gitnessHomeDir, blobDir)
|
||||
}
|
||||
return blob.Config{
|
||||
Provider: config.BlobStore.Provider,
|
||||
Bucket: config.BlobStore.Bucket,
|
||||
KeyPath: config.BlobStore.KeyPath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ProvideGitRPCServerConfig loads the gitrpc server config from the environment.
|
||||
// It backfills certain config elements to work with cmdone.
|
||||
func ProvideGitRPCServerConfig() (server.Config, error) {
|
||||
|
|
|
@ -9,6 +9,8 @@ package main
|
|||
|
||||
import (
|
||||
"context"
|
||||
"github.com/harness/gitness/app/api/controller/upload"
|
||||
"github.com/harness/gitness/blob"
|
||||
|
||||
checkcontroller "github.com/harness/gitness/app/api/controller/check"
|
||||
"github.com/harness/gitness/app/api/controller/connector"
|
||||
|
@ -83,6 +85,8 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
|||
bootstrap.WireSet,
|
||||
cliserver.ProvideDatabaseConfig,
|
||||
database.WireSet,
|
||||
cliserver.ProvideBlobStoreConfig,
|
||||
blob.WireSet,
|
||||
dbtx.WireSet,
|
||||
cache.WireSet,
|
||||
router.WireSet,
|
||||
|
@ -96,6 +100,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
|
|||
controllerwebhook.WireSet,
|
||||
serviceaccount.WireSet,
|
||||
user.WireSet,
|
||||
upload.WireSet,
|
||||
service.WireSet,
|
||||
principal.WireSet,
|
||||
system.WireSet,
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"github.com/harness/gitness/app/api/controller/system"
|
||||
"github.com/harness/gitness/app/api/controller/template"
|
||||
"github.com/harness/gitness/app/api/controller/trigger"
|
||||
"github.com/harness/gitness/app/api/controller/upload"
|
||||
"github.com/harness/gitness/app/api/controller/user"
|
||||
webhook2 "github.com/harness/gitness/app/api/controller/webhook"
|
||||
"github.com/harness/gitness/app/auth/authn"
|
||||
|
@ -58,6 +59,7 @@ import (
|
|||
"github.com/harness/gitness/app/store/database"
|
||||
"github.com/harness/gitness/app/store/logs"
|
||||
"github.com/harness/gitness/app/url"
|
||||
"github.com/harness/gitness/blob"
|
||||
"github.com/harness/gitness/cli/server"
|
||||
"github.com/harness/gitness/encrypt"
|
||||
"github.com/harness/gitness/events"
|
||||
|
@ -218,7 +220,16 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||
principalController := principal.ProvideController(principalStore)
|
||||
checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitrpcInterface)
|
||||
systemController := system.NewController(principalStore, config)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, repoController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, serviceaccountController, controller, principalController, checkController, systemController)
|
||||
blobConfig, err := server.ProvideBlobStoreConfig(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blobStore, err := blob.ProvideStore(blobConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
uploadController := upload.ProvideController(authorizer, repoStore, blobStore)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, repoController, executionController, logsController, spaceController, pipelineController, secretController, triggerController, connectorController, templateController, pluginController, pullreqController, webhookController, githookController, serviceaccountController, controller, principalController, checkController, systemController, uploadController)
|
||||
gitHandler := router.ProvideGitHandler(config, provider, repoStore, authenticator, authorizer, gitrpcInterface, repoController)
|
||||
webHandler := router.ProvideWebHandler(config)
|
||||
routerRouter := router.ProvideRouter(config, apiHandler, gitHandler, webHandler, provider)
|
||||
|
|
26
go.mod
26
go.mod
|
@ -5,6 +5,7 @@ go 1.19
|
|||
replace github.com/docker/docker => github.com/docker/engine v17.12.0-ce-rc1.0.20200309214505-aa6a9891b09c+incompatible
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.33.0
|
||||
code.gitea.io/gitea v1.17.2
|
||||
github.com/Masterminds/squirrel v1.5.1
|
||||
github.com/adrg/xdg v0.3.2
|
||||
|
@ -27,6 +28,7 @@ require (
|
|||
github.com/go-redsync/redsync/v4 v4.7.1
|
||||
github.com/golang-jwt/jwt v3.2.2+incompatible
|
||||
github.com/google/go-cmp v0.5.9
|
||||
github.com/google/uuid v1.3.1
|
||||
github.com/google/wire v0.5.0
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75
|
||||
github.com/gotidy/ptr v1.4.0
|
||||
|
@ -58,15 +60,16 @@ require (
|
|||
golang.org/x/sync v0.3.0
|
||||
golang.org/x/term v0.12.0
|
||||
golang.org/x/text v0.13.0
|
||||
google.golang.org/grpc v1.55.0
|
||||
google.golang.org/protobuf v1.30.0
|
||||
google.golang.org/grpc v1.56.2
|
||||
google.golang.org/protobuf v1.31.0
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.110.0 // indirect
|
||||
cloud.google.com/go/compute v1.18.0 // indirect
|
||||
cloud.google.com/go v0.110.4 // indirect
|
||||
cloud.google.com/go/compute v1.20.1 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.2.3 // indirect
|
||||
cloud.google.com/go/iam v1.1.0 // indirect
|
||||
dario.cat/mergo v1.0.0 // indirect
|
||||
github.com/99designs/basicauth-go v0.0.0-20160802081356-2a93ba0f464d // indirect
|
||||
github.com/99designs/httpsignatures-go v0.0.0-20170731043157-88528bf4ca7e // indirect
|
||||
|
@ -88,9 +91,9 @@ require (
|
|||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/google/uuid v1.3.1 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.7.0 // indirect
|
||||
github.com/google/s2a-go v0.1.4 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
|
||||
github.com/natessilva/dag v0.0.0-20180124060714-7194b8dcc5c4 // indirect
|
||||
|
@ -103,9 +106,12 @@ require (
|
|||
github.com/prometheus/procfs v0.9.0 // indirect
|
||||
github.com/skeema/knownhosts v1.2.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
golang.org/x/oauth2 v0.6.0 // indirect
|
||||
google.golang.org/api v0.110.0 // indirect
|
||||
golang.org/x/oauth2 v0.10.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 // indirect
|
||||
google.golang.org/api v0.132.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
|
@ -160,7 +166,7 @@ require (
|
|||
golang.org/x/net v0.15.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/tools v0.13.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 // indirect
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
|
||||
gopkg.in/ini.v1 v1.66.4 // indirect
|
||||
gopkg.in/warnings.v0 v0.1.2 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
|
|
71
go.sum
71
go.sum
|
@ -1,16 +1,17 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.110.0 h1:Zc8gqp3+a9/Eyph2KDmcGaPtbKRIoqq4YTlL4NMD0Ys=
|
||||
cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY=
|
||||
cloud.google.com/go/compute v1.18.0 h1:FEigFqoDbys2cvFkZ9Fjq4gnHBP55anJ0yQyau2f9oY=
|
||||
cloud.google.com/go/compute v1.18.0/go.mod h1:1X7yHxec2Ga+Ss6jPyjxRxpu2uu7PLgsOVXvgU0yacs=
|
||||
cloud.google.com/go v0.110.4 h1:1JYyxKMN9hd5dR2MYTPWkGUgcoxVVhg0LKNKEo0qvmk=
|
||||
cloud.google.com/go v0.110.4/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI=
|
||||
cloud.google.com/go/compute v1.20.1 h1:6aKEtlUiwEpJzM001l0yFkpXmUVXaN8W+fbkb2AZNbg=
|
||||
cloud.google.com/go/compute v1.20.1/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM=
|
||||
cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY=
|
||||
cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA=
|
||||
cloud.google.com/go/iam v0.12.0 h1:DRtTY29b75ciH6Ov1PHb4/iat2CLCvrOm40Q0a6DFpE=
|
||||
cloud.google.com/go/longrunning v0.4.1 h1:v+yFJOfKC3yZdY6ZUI933pIYdhyhV8S3NpWrXWmg7jM=
|
||||
cloud.google.com/go/iam v1.1.0 h1:67gSqaPukx7O8WLLHMa0PNs3EBGd2eE4d+psbO/CO94=
|
||||
cloud.google.com/go/iam v1.1.0/go.mod h1:nxdHjaKfCr7fNYx/HJMM8LgiMugmveWlkatear5gVyk=
|
||||
cloud.google.com/go/profiler v0.3.1 h1:b5got9Be9Ia0HVvyt7PavWxXEht15B9lWnigdvHtxOc=
|
||||
cloud.google.com/go/profiler v0.3.1/go.mod h1:GsG14VnmcMFQ9b+kq71wh3EKMZr3WRMgLzNiFRpW7tE=
|
||||
cloud.google.com/go/storage v1.28.1 h1:F5QDG5ChchaAVQhINh24U99OWHURqrW8OmQcGKXcbgI=
|
||||
cloud.google.com/go/storage v1.33.0 h1:PVrDOkIC8qQVa1P3SXGpQvfuJhN2LHOoyZvWs8D2X5M=
|
||||
cloud.google.com/go/storage v1.33.0/go.mod h1:Hhh/dogNRGca7IWv1RC2YqEn0c0G77ctA/OxflYkiD8=
|
||||
code.gitea.io/gitea v1.17.2 h1:NRcVr07jF+za4d0NZZlJXeCuQK5FfHMtjPDjq4u3UiY=
|
||||
code.gitea.io/gitea v1.17.2/go.mod h1:sovminOoSsc8IC2T29rX9+MmaboHTu8QDEvJjaSqIXg=
|
||||
dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk=
|
||||
|
@ -50,6 +51,7 @@ github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137/go.mod h1:OMCwj8V
|
|||
github.com/andybalholm/brotli v1.0.3/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
|
||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/antonmedv/expr v1.15.2 h1:afFXpDWIC2n3bF+kTZE1JvFo+c34uaM3sTqh8z0xfdU=
|
||||
github.com/antonmedv/expr v1.15.2/go.mod h1:0E/6TxnOlRNp81GMzX9QfDPAmHo2Phg00y4JUv1ihsE=
|
||||
github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
|
||||
|
@ -94,6 +96,11 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
|
|||
github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs=
|
||||
github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ=
|
||||
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
|
||||
github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
|
||||
|
@ -178,6 +185,8 @@ github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4s
|
|||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
|
||||
|
@ -290,10 +299,13 @@ 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/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c h1:lvddKcYTQ545ADhBujtIJmqQrZBDsGo7XIMbAQe/sNY=
|
||||
github.com/google/pprof v0.0.0-20221103000818-d260c55eee4c/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
||||
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
|
||||
github.com/google/s2a-go v0.1.4 h1:1kZ/sQM3srePvKs3tXAvQzo66XfcReoqFpIpIccE7Oc=
|
||||
github.com/google/s2a-go v0.1.4/go.mod h1:Ej+mSEMGRnqRzjc7VtF+jdBwYG5fuJfiZ8ELkjEwM0A=
|
||||
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
github.com/google/subcommands v1.2.0 h1:vWQspBTo2nEqTUFita5/KeEWlUL8kQObDFbub/EN9oE=
|
||||
github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
|
||||
|
@ -303,10 +315,10 @@ github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4=
|
|||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
|
||||
github.com/google/wire v0.5.0/go.mod h1:ngWDr9Qvq3yZA10YrxfyGELY/AFWGVpy9c1LTRi1EoU=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3 h1:yk9/cqRKtT9wXZSsRH9aurXEpJX+U6FLtpYTdC3R06k=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.3/go.mod h1:AwSRAtLfXpU5Nm3pW+v7rGDHp09LsPtGY9MduiEsR9k=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0 h1:IcsPKeInNvYi7eqSaDjiZqDDKu5rsmunY0Y1YupQSSQ=
|
||||
github.com/googleapis/gax-go/v2 v2.7.0/go.mod h1:TEop28CZZQ2y+c0VxMUmu1lV+fQx57QpBWsYpwqHJx8=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas=
|
||||
github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU=
|
||||
github.com/googleapis/gnostic v0.2.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 h1:f0n1xnMSmBLzVfsMMvriDyA75NB/oBgILX2GcHXIQzY=
|
||||
|
@ -324,6 +336,7 @@ github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaW
|
|||
github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y=
|
||||
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/guregu/null v4.0.0+incompatible h1:4zw0ckM7ECd6FNNddc3Fu4aty9nTlpkkzH7dPn4/4Gw=
|
||||
github.com/guregu/null v4.0.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM=
|
||||
github.com/h2non/gock v1.0.9 h1:17gCehSo8ZOgEsFKpQgqHiR7VLyjxdAG3lkhVvO9QZU=
|
||||
|
@ -619,6 +632,7 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn
|
|||
github.com/robfig/cron/v3 v3.0.0 h1:kQ6Cb7aHOHTSzNVNEhmp8EcWKLb4CbiMW9h9VyIhO4E=
|
||||
github.com/robfig/cron/v3 v3.0.0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M=
|
||||
github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ=
|
||||
|
@ -719,6 +733,7 @@ go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
|
|||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
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=
|
||||
go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
|
@ -753,6 +768,7 @@ golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm
|
|||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
||||
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/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-20220314234659-1baeb1ce4c0b/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
|
@ -796,6 +812,7 @@ golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
|
@ -816,8 +833,9 @@ golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
|||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
||||
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.10.0 h1:zHCpF2Khkwy4mMB4bv0U37YtJdTGW8jI0glAApi0Kh8=
|
||||
golang.org/x/oauth2 v0.10.0/go.mod h1:kTpgurOux7LqtuxjuyZa4Gj2gdezIt/jQtGnNFfypQI=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
@ -898,6 +916,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.4/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.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.4.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=
|
||||
|
@ -940,9 +959,10 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T
|
|||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
||||
google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
|
||||
google.golang.org/api v0.110.0 h1:l+rh0KYUooe9JGbGVx71tbFo4SMbMTXK3I3ia2QSEeU=
|
||||
google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI=
|
||||
google.golang.org/api v0.132.0 h1:8t2/+qZ26kAOGSmOiHwVycqVaDg7q3JDILrNi/Z6rvc=
|
||||
google.golang.org/api v0.132.0/go.mod h1:AeTBC6GpJnJSRJjktDcPX0QwtS8pGYZOV6MSuSCusw0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
|
@ -955,9 +975,14 @@ google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRn
|
|||
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4 h1:DdoeryqhaXp1LtT/emMP1BRJPHHKFi5akj/nbx/zNTA=
|
||||
google.golang.org/genproto v0.0.0-20230306155012-7f2fa6fef1f4/go.mod h1:NWraEVixdDnqcqQ30jipen1STv2r/n24Wb7twVTGR4s=
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 h1:Au6te5hbKUV8pIYWHqOUZ1pva5qK/rwbIhoXEUB9Lu8=
|
||||
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:O9kGHb51iE/nOGvQaDUuadVYqovW56s5emA88lQnj6Y=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130 h1:XVeBY8d/FaK4848myy41HBqnDwvxeV3zMZhwN1TvAMU=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20230706204954-ccb25ca9f130/go.mod h1:mPBs5jNgx2GuQGvFwUvVKqtn6HsUw9nP64BedgvqEsQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 h1:bVf09lpb+OJbByTj913DRJioFFAjf/ZGxEz7MajTp2U=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98/go.mod h1:TUfxEVdsvPg18p6AslUXFoLdpED4oBnGwyqk3dV1XzM=
|
||||
google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
|
||||
|
@ -970,9 +995,12 @@ google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQ
|
|||
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.55.0 h1:3Oj82/tFSCeUrRTg/5E/7d/W5A1tj6Ky1ABAuZuv5ag=
|
||||
google.golang.org/grpc v1.55.0/go.mod h1:iYEXKGkEBhg1PjZQvoYEVPTDkHo1/bjTnfwTeGONTY8=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.45.0/go.mod h1:lN7owxKUQEqMfSyQikvvk5tf/6zMPsrK+ONuO11+0rQ=
|
||||
google.golang.org/grpc v1.56.2 h1:fVRFRnXvU+x6C4IlHZewvJOVHoOv1TUuQyoRsYnB4bI=
|
||||
google.golang.org/grpc v1.56.2/go.mod h1:I9bI3vqKfayGqPUAwGdOSu7kt6oIJLixfffKrpXqQ9s=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
@ -985,8 +1013,8 @@ 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.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||
google.golang.org/protobuf v1.30.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 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
@ -1009,6 +1037,7 @@ gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRN
|
|||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
@ -17,6 +17,7 @@ package types
|
|||
import (
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/blob"
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/lock"
|
||||
"github.com/harness/gitness/pubsub"
|
||||
|
@ -123,6 +124,18 @@ type Config struct {
|
|||
Datasource string `envconfig:"GITNESS_DATABASE_DATASOURCE" default:"database.sqlite3"`
|
||||
}
|
||||
|
||||
// BlobStore defines the blob storage configuration parameters.
|
||||
BlobStore struct {
|
||||
// Provider is a name of blob storage service like filesystem or gcs
|
||||
Provider blob.Provider `envconfig:"GITNESS_BLOBSTORE_PROVIDER" default:"filesystem"`
|
||||
// Bucket is a path to the directory where the files will be stored when using filesystem blob storage,
|
||||
// in case of gcs provider this will be the actual bucket where the images are stored.
|
||||
Bucket string `envconfig:"GITNESS_BLOBSTORE_BUCKET"`
|
||||
|
||||
// In case of GCS provider, this is expected to be the path to the service account key file.
|
||||
KeyPath string `envconfig:"GITNESS_BLOBSTORE_KEY_PATH" default:""`
|
||||
}
|
||||
|
||||
// Token defines token configuration parameters.
|
||||
Token struct {
|
||||
CookieName string `envconfig:"GITNESS_TOKEN_COOKIE_NAME" default:"token"`
|
||||
|
|
Loading…
Reference in New Issue