mirror of https://github.com/harness/drone.git
[Webhook] Add url.Provider, Add principal to branch webhooks (#163)
parent
4938718aca
commit
2006f769c9
|
@ -12,7 +12,6 @@ import (
|
|||
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
gitrpcevents "github.com/harness/gitness/gitrpc/events"
|
||||
gitrpcserver "github.com/harness/gitness/gitrpc/server"
|
||||
"github.com/harness/gitness/harness/auth/authn"
|
||||
"github.com/harness/gitness/harness/auth/authz"
|
||||
|
@ -30,8 +29,10 @@ import (
|
|||
"github.com/harness/gitness/internal/api/controller/user"
|
||||
controllerwebhook "github.com/harness/gitness/internal/api/controller/webhook"
|
||||
"github.com/harness/gitness/internal/cron"
|
||||
eventsgit "github.com/harness/gitness/internal/events/git"
|
||||
"github.com/harness/gitness/internal/server"
|
||||
"github.com/harness/gitness/internal/store/database"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/internal/webhook"
|
||||
gitnesstypes "github.com/harness/gitness/types"
|
||||
|
||||
|
@ -47,6 +48,7 @@ func initSystem(ctx context.Context, config *gitnesstypes.Config) (*system, erro
|
|||
database.WireSet,
|
||||
server.WireSet,
|
||||
cron.WireSet,
|
||||
url.WireSet,
|
||||
space.WireSet,
|
||||
repo.WireSet,
|
||||
pullreq.WireSet,
|
||||
|
@ -54,7 +56,7 @@ func initSystem(ctx context.Context, config *gitnesstypes.Config) (*system, erro
|
|||
user.WireSet,
|
||||
service.WireSet,
|
||||
serviceaccount.WireSet,
|
||||
gitrpcevents.WireSet,
|
||||
eventsgit.WireSet,
|
||||
gitrpcserver.WireSet,
|
||||
gitrpc.WireSet,
|
||||
types.LoadConfig,
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
events2 "github.com/harness/gitness/gitrpc/events"
|
||||
server2 "github.com/harness/gitness/gitrpc/server"
|
||||
"github.com/harness/gitness/harness/auth/authn"
|
||||
"github.com/harness/gitness/harness/auth/authz"
|
||||
|
@ -28,9 +27,11 @@ import (
|
|||
"github.com/harness/gitness/internal/api/controller/user"
|
||||
webhook2 "github.com/harness/gitness/internal/api/controller/webhook"
|
||||
"github.com/harness/gitness/internal/cron"
|
||||
events2 "github.com/harness/gitness/internal/events/git"
|
||||
router2 "github.com/harness/gitness/internal/router"
|
||||
"github.com/harness/gitness/internal/server"
|
||||
"github.com/harness/gitness/internal/store/database"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/internal/webhook"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
@ -80,8 +81,12 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
spaceStore := database.ProvideSpaceStore(db, pathTransformation)
|
||||
repoStore := database.ProvideRepoStore(db, pathTransformation)
|
||||
serviceaccountController := serviceaccount.NewController(serviceAccount, authorizer, principalStore, spaceStore, repoStore, tokenStore)
|
||||
provider, err := url.ProvideURLProvider(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
checkSpace := check.ProvideSpaceCheck()
|
||||
spaceController := space.ProvideController(config, checkSpace, authorizer, spaceStore, repoStore, principalStore)
|
||||
spaceController := space.ProvideController(provider, checkSpace, authorizer, spaceStore, repoStore, principalStore)
|
||||
accountClient, err := client.ProvideAccountClient(serviceJWTProvider, typesConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -96,7 +101,7 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoController := repo.ProvideController(config, checkRepo, authorizer, spaceStore, repoStore, principalStore, gitrpcInterface)
|
||||
repoController := repo.ProvideController(config, provider, checkRepo, authorizer, spaceStore, repoStore, principalStore, gitrpcInterface)
|
||||
pullReqStore := database.ProvidePullReqStore(db)
|
||||
pullReqActivityStore := database.ProvidePullReqActivityStore(db)
|
||||
pullreqController := pullreq.ProvideController(db, authorizer, pullReqStore, pullReqActivityStore, repoStore, principalStore, gitrpcInterface)
|
||||
|
@ -116,13 +121,13 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookServer, err := webhook.ProvideServer(ctx, webhookConfig, readerFactory, webhookStore, webhookExecutionStore, repoStore)
|
||||
webhookServer, err := webhook.ProvideServer(ctx, webhookConfig, readerFactory, webhookStore, webhookExecutionStore, repoStore, provider, principalStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookController := webhook2.ProvideController(config, db, authorizer, webhookStore, webhookExecutionStore, repoStore, webhookServer)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, accountClient, controller, spaceController, repoController, pullreqController, webhookController)
|
||||
gitHandler := router.ProvideGitHandler(config, repoStore, authenticator, authorizer, gitrpcInterface)
|
||||
gitHandler := router.ProvideGitHandler(config, provider, repoStore, authenticator, authorizer, gitrpcInterface)
|
||||
webHandler := router2.ProvideWebHandler(config)
|
||||
routerRouter := router2.ProvideRouter(apiHandler, gitHandler, webHandler)
|
||||
serverServer := server.ProvideServer(config, routerRouter)
|
||||
|
|
|
@ -12,7 +12,6 @@ import (
|
|||
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
gitrpcevents "github.com/harness/gitness/gitrpc/events"
|
||||
gitrpcserver "github.com/harness/gitness/gitrpc/server"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
"github.com/harness/gitness/internal/api/controller/repo"
|
||||
|
@ -24,10 +23,12 @@ import (
|
|||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/bootstrap"
|
||||
"github.com/harness/gitness/internal/cron"
|
||||
eventsgit "github.com/harness/gitness/internal/events/git"
|
||||
"github.com/harness/gitness/internal/router"
|
||||
"github.com/harness/gitness/internal/server"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/store/database"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/internal/webhook"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
@ -45,6 +46,7 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
router.WireSet,
|
||||
server.WireSet,
|
||||
cron.WireSet,
|
||||
url.WireSet,
|
||||
space.WireSet,
|
||||
repo.WireSet,
|
||||
pullreq.WireSet,
|
||||
|
@ -53,7 +55,7 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
user.WireSet,
|
||||
authn.WireSet,
|
||||
authz.WireSet,
|
||||
gitrpcevents.WireSet,
|
||||
eventsgit.WireSet,
|
||||
gitrpcserver.WireSet,
|
||||
gitrpc.WireSet,
|
||||
store.WireSet,
|
||||
|
|
|
@ -10,7 +10,6 @@ import (
|
|||
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
events2 "github.com/harness/gitness/gitrpc/events"
|
||||
server2 "github.com/harness/gitness/gitrpc/server"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
"github.com/harness/gitness/internal/api/controller/repo"
|
||||
|
@ -22,10 +21,12 @@ import (
|
|||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/bootstrap"
|
||||
"github.com/harness/gitness/internal/cron"
|
||||
events2 "github.com/harness/gitness/internal/events/git"
|
||||
"github.com/harness/gitness/internal/router"
|
||||
"github.com/harness/gitness/internal/server"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/store/database"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/internal/webhook"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
@ -46,6 +47,10 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
controller := user.NewController(checkUser, authorizer, principalStore, tokenStore)
|
||||
bootstrapBootstrap := bootstrap.ProvideBootstrap(config, controller)
|
||||
authenticator := authn.ProvideAuthenticator(principalStore, tokenStore)
|
||||
provider, err := url.ProvideURLProvider(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
checkRepo := check.ProvideRepoCheck()
|
||||
pathTransformation := store.ProvidePathTransformation()
|
||||
spaceStore := database.ProvideSpaceStore(db, pathTransformation)
|
||||
|
@ -55,9 +60,9 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repoController := repo.ProvideController(config, checkRepo, authorizer, spaceStore, repoStore, principalStore, gitrpcInterface)
|
||||
repoController := repo.ProvideController(config, provider, checkRepo, authorizer, spaceStore, repoStore, principalStore, gitrpcInterface)
|
||||
checkSpace := check.ProvideSpaceCheck()
|
||||
spaceController := space.ProvideController(config, checkSpace, authorizer, spaceStore, repoStore, principalStore)
|
||||
spaceController := space.ProvideController(provider, checkSpace, authorizer, spaceStore, repoStore, principalStore)
|
||||
pullReqStore := database.ProvidePullReqStore(db)
|
||||
pullReqActivityStore := database.ProvidePullReqActivityStore(db)
|
||||
pullreqController := pullreq.ProvideController(db, authorizer, pullReqStore, pullReqActivityStore, repoStore, principalStore, gitrpcInterface)
|
||||
|
@ -77,7 +82,7 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
webhookServer, err := webhook.ProvideServer(ctx, webhookConfig, readerFactory, webhookStore, webhookExecutionStore, repoStore)
|
||||
webhookServer, err := webhook.ProvideServer(ctx, webhookConfig, readerFactory, webhookStore, webhookExecutionStore, repoStore, provider, principalStore)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -85,7 +90,7 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
|||
serviceAccount := check.ProvideServiceAccountCheck()
|
||||
serviceaccountController := serviceaccount.NewController(serviceAccount, authorizer, principalStore, spaceStore, repoStore, tokenStore)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, repoController, spaceController, pullreqController, webhookController, serviceaccountController, controller)
|
||||
gitHandler := router.ProvideGitHandler(config, repoStore, authenticator, authorizer, gitrpcInterface)
|
||||
gitHandler := router.ProvideGitHandler(config, provider, repoStore, authenticator, authorizer, gitrpcInterface)
|
||||
webHandler := router.ProvideWebHandler(config)
|
||||
routerRouter := router.ProvideRouter(apiHandler, gitHandler, webHandler)
|
||||
serverServer := server.ProvideServer(config, routerRouter)
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright 2022 Harness Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Polyform Free Trial License
|
||||
// that can be found in the LICENSE.md file for this repository.
|
||||
|
||||
package events
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var (
|
||||
errDiscardEvent = &discardEventError{}
|
||||
)
|
||||
|
||||
// discardEventError is an error which, if returned by the event handler,
|
||||
// causes the source event to be discarded despite any erros.
|
||||
type discardEventError struct {
|
||||
inner error
|
||||
}
|
||||
|
||||
func NewDiscardEventError(inner error) error {
|
||||
return &discardEventError{
|
||||
inner: inner,
|
||||
}
|
||||
}
|
||||
|
||||
func NewDiscardEventErrorf(format string, args ...interface{}) error {
|
||||
return &discardEventError{
|
||||
inner: fmt.Errorf(format, args...),
|
||||
}
|
||||
}
|
||||
|
||||
func (e *discardEventError) Error() string {
|
||||
return fmt.Sprintf("discarding requested due to: %s", e.inner)
|
||||
}
|
||||
|
||||
func (e *discardEventError) Unwrap() error {
|
||||
return e.inner
|
||||
}
|
||||
|
||||
func (e *discardEventError) Is(target error) bool {
|
||||
// NOTE: it's an internal event and we only ever check with the singleton instance
|
||||
return errors.Is(target, errDiscardEvent)
|
||||
}
|
|
@ -198,7 +198,16 @@ func ReaderRegisterEvent[T interface{}](reader *GenericReader,
|
|||
ctx = log.WithContext(ctx)
|
||||
|
||||
// call provided handler with correctly typed payload
|
||||
return fn(ctx, &event)
|
||||
err = fn(ctx, &event)
|
||||
|
||||
// handle discardEventError
|
||||
if errors.Is(err, errDiscardEvent) {
|
||||
log.Warn().Err(err).Msgf("discarding event '%s'", event.ID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// any other error we return as is
|
||||
return err
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ package repo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
apiauth "github.com/harness/gitness/internal/api/auth"
|
||||
|
@ -58,8 +59,13 @@ func (c *Controller) CommitFiles(ctx context.Context, session *auth.Session,
|
|||
}
|
||||
}
|
||||
|
||||
writeParams, err := CreateRPCWriteParams(ctx, c.urlProvider, session, repo)
|
||||
if err != nil {
|
||||
return CommitFilesResponse{}, fmt.Errorf("failed to create RPC write params: %w", err)
|
||||
}
|
||||
|
||||
commit, err := c.gitRPCClient.CommitFiles(ctx, &gitrpc.CommitFilesParams{
|
||||
WriteParams: CreateRPCWriteParams(session, repo),
|
||||
WriteParams: writeParams,
|
||||
Title: in.Title,
|
||||
Message: in.Message,
|
||||
Branch: in.Branch,
|
||||
|
|
|
@ -5,17 +5,23 @@
|
|||
package repo
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/internal/api/request"
|
||||
"github.com/harness/gitness/internal/auth"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
defaultBranch string
|
||||
gitBaseURL string
|
||||
urlProvider *url.Provider
|
||||
repoCheck check.Repo
|
||||
authorizer authz.Authorizer
|
||||
spaceStore store.SpaceStore
|
||||
|
@ -26,7 +32,7 @@ type Controller struct {
|
|||
|
||||
func NewController(
|
||||
defaultBranch string,
|
||||
gitBaseURL string,
|
||||
urlProvider *url.Provider,
|
||||
repoCheck check.Repo,
|
||||
authorizer authz.Authorizer,
|
||||
spaceStore store.SpaceStore,
|
||||
|
@ -36,7 +42,7 @@ func NewController(
|
|||
) *Controller {
|
||||
return &Controller{
|
||||
defaultBranch: defaultBranch,
|
||||
gitBaseURL: gitBaseURL,
|
||||
urlProvider: urlProvider,
|
||||
repoCheck: repoCheck,
|
||||
authorizer: authorizer,
|
||||
spaceStore: spaceStore,
|
||||
|
@ -48,10 +54,25 @@ func NewController(
|
|||
|
||||
// CreateRPCWriteParams creates base write parameters for gitrpc write operations.
|
||||
// IMPORTANT: session & repo are assumed to be not nil!
|
||||
func CreateRPCWriteParams(session *auth.Session, repo *types.Repository) gitrpc.WriteParams {
|
||||
func CreateRPCWriteParams(ctx context.Context, urlProvider *url.Provider,
|
||||
session *auth.Session, repo *types.Repository) (gitrpc.WriteParams, error) {
|
||||
requestID, ok := request.RequestIDFrom(ctx)
|
||||
if !ok {
|
||||
// best effort retrieving of requestID - log in case we can't find it but don't fail operation.
|
||||
log.Ctx(ctx).Warn().Msg("operation doesn't have a requestID in the context.")
|
||||
}
|
||||
|
||||
// generate envars (add everything githook CLI needs for execution)
|
||||
// TODO: envVars := githook.GenerateGitHookEnvironmentVariables(repo, session.Principal)
|
||||
envVars := map[string]string{}
|
||||
envVars := map[string]string{"X-Request-Id": requestID}
|
||||
// envVars, err := githook.GenerateEnvironmentVariables(&githook.Payload{
|
||||
// BaseURL: urlProvider.GetAPIBaseURL(),
|
||||
// RepoID: repo.ID,
|
||||
// PrincipalID: session.Principal.ID,
|
||||
// RequestID: requestID,
|
||||
// })
|
||||
// if err != nil {
|
||||
// return gitrpc.WriteParams{}, fmt.Errorf("failed to generate git hook environment variables: %w", err)
|
||||
// }
|
||||
|
||||
return gitrpc.WriteParams{
|
||||
Actor: gitrpc.Identity{
|
||||
|
@ -60,7 +81,7 @@ func CreateRPCWriteParams(session *auth.Session, repo *types.Repository) gitrpc.
|
|||
},
|
||||
RepoUID: repo.GitUID,
|
||||
EnvVars: envVars,
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateRPCReadParams creates base read parameters for gitrpc read operations.
|
||||
|
|
|
@ -142,10 +142,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
|
|||
}
|
||||
|
||||
// populate repo url
|
||||
repo.GitURL, err = GenerateRepoGitURL(c.gitBaseURL, repo.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
repo.GitURL = c.urlProvider.GenerateRepoCloneURL(repo.Path)
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
|
|
@ -44,11 +44,16 @@ func (c *Controller) CreateBranch(ctx context.Context, session *auth.Session,
|
|||
|
||||
err = checkBranchName(in.Name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("branch name failed check: %w", err)
|
||||
}
|
||||
|
||||
writeParams, err := CreateRPCWriteParams(ctx, c.urlProvider, session, repo)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create RPC write params: %w", err)
|
||||
}
|
||||
|
||||
rpcOut, err := c.gitRPCClient.CreateBranch(ctx, &gitrpc.CreateBranchParams{
|
||||
WriteParams: CreateRPCWriteParams(session, repo),
|
||||
WriteParams: writeParams,
|
||||
BranchName: in.Name,
|
||||
Target: *in.Target,
|
||||
})
|
||||
|
|
|
@ -6,6 +6,7 @@ package repo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
apiauth "github.com/harness/gitness/internal/api/auth"
|
||||
|
@ -33,8 +34,13 @@ func (c *Controller) DeleteBranch(ctx context.Context, session *auth.Session, re
|
|||
return usererror.ErrDefaultBranchCantBeDeleted
|
||||
}
|
||||
|
||||
writeParams, err := CreateRPCWriteParams(ctx, c.urlProvider, session, repo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create RPC write params: %w", err)
|
||||
}
|
||||
|
||||
err = c.gitRPCClient.DeleteBranch(ctx, &gitrpc.DeleteBranchParams{
|
||||
WriteParams: CreateRPCWriteParams(session, repo),
|
||||
WriteParams: writeParams,
|
||||
BranchName: branchName,
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
@ -6,10 +6,6 @@ package repo
|
|||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
|
||||
apiauth "github.com/harness/gitness/internal/api/auth"
|
||||
"github.com/harness/gitness/internal/auth"
|
||||
|
@ -28,23 +24,8 @@ func (c *Controller) Find(ctx context.Context, session *auth.Session, repoRef st
|
|||
return nil, err
|
||||
}
|
||||
|
||||
repo.GitURL, err = GenerateRepoGitURL(c.gitBaseURL, repo.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// backfil clone url
|
||||
repo.GitURL = c.urlProvider.GenerateRepoCloneURL(repo.Path)
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func GenerateRepoGitURL(gitBaseURL string, repoPath string) (string, error) {
|
||||
repoPath = path.Clean(repoPath)
|
||||
if !strings.HasSuffix(repoPath, ".git") {
|
||||
repoPath += ".git"
|
||||
}
|
||||
gitURL, err := url.JoinPath(gitBaseURL, repoPath)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("failed to join base url '%s' with path '%s': %w", gitBaseURL, repoPath, err)
|
||||
}
|
||||
|
||||
return gitURL, nil
|
||||
}
|
||||
|
|
|
@ -61,11 +61,8 @@ func (c *Controller) Update(ctx context.Context, session *auth.Session,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
// populate repo url
|
||||
repo.GitURL, err = GenerateRepoGitURL(c.gitBaseURL, repo.Path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// backfill repo url
|
||||
repo.GitURL = c.urlProvider.GenerateRepoCloneURL(repo.Path)
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
||||
|
@ -19,9 +20,10 @@ var WireSet = wire.NewSet(
|
|||
ProvideController,
|
||||
)
|
||||
|
||||
func ProvideController(config *types.Config, repoCheck check.Repo, authorizer authz.Authorizer,
|
||||
spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore,
|
||||
func ProvideController(config *types.Config, urlProvider *url.Provider,
|
||||
repoCheck check.Repo, authorizer authz.Authorizer, spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore, principalStore store.PrincipalStore,
|
||||
rpcClient gitrpc.Interface) *Controller {
|
||||
return NewController(config.Git.DefaultBranch, config.Git.BaseURL,
|
||||
return NewController(config.Git.DefaultBranch, urlProvider,
|
||||
repoCheck, authorizer, spaceStore, repoStore, principalStore, rpcClient)
|
||||
}
|
||||
|
|
|
@ -7,11 +7,12 @@ package space
|
|||
import (
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types/check"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
gitBaseURL string
|
||||
urlProvider *url.Provider
|
||||
spaceCheck check.Space
|
||||
authorizer authz.Authorizer
|
||||
spaceStore store.SpaceStore
|
||||
|
@ -19,10 +20,11 @@ type Controller struct {
|
|||
principalStore store.PrincipalStore
|
||||
}
|
||||
|
||||
func NewController(gitBaseURL string, spaceCheck check.Space, authorizer authz.Authorizer, spaceStore store.SpaceStore,
|
||||
repoStore store.RepoStore, principalStore store.PrincipalStore) *Controller {
|
||||
func NewController(urlProvider *url.Provider, spaceCheck check.Space,
|
||||
authorizer authz.Authorizer, spaceStore store.SpaceStore, repoStore store.RepoStore,
|
||||
principalStore store.PrincipalStore) *Controller {
|
||||
return &Controller{
|
||||
gitBaseURL: gitBaseURL,
|
||||
urlProvider: urlProvider,
|
||||
spaceCheck: spaceCheck,
|
||||
authorizer: authorizer,
|
||||
spaceStore: spaceStore,
|
||||
|
|
|
@ -9,7 +9,6 @@ import (
|
|||
"fmt"
|
||||
|
||||
apiauth "github.com/harness/gitness/internal/api/auth"
|
||||
"github.com/harness/gitness/internal/api/controller/repo"
|
||||
"github.com/harness/gitness/internal/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
@ -39,11 +38,9 @@ func (c *Controller) ListRepositories(ctx context.Context, session *auth.Session
|
|||
return nil, 0, fmt.Errorf("failed to list child repos: %w", err)
|
||||
}
|
||||
|
||||
for _, r := range repos {
|
||||
r.GitURL, err = repo.GenerateRepoGitURL(c.gitBaseURL, r.Path)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
// backfill URLs
|
||||
for _, repo := range repos {
|
||||
repo.GitURL = c.urlProvider.GenerateRepoCloneURL(repo.Path)
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -7,7 +7,7 @@ package space
|
|||
import (
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types/check"
|
||||
|
||||
"github.com/google/wire"
|
||||
|
@ -18,7 +18,7 @@ var WireSet = wire.NewSet(
|
|||
ProvideController,
|
||||
)
|
||||
|
||||
func ProvideController(config *types.Config, spaceCheck check.Space, authorizer authz.Authorizer,
|
||||
func ProvideController(urlProvider *url.Provider, spaceCheck check.Space, authorizer authz.Authorizer,
|
||||
spaceStore store.SpaceStore, repoStore store.RepoStore, principalStore store.PrincipalStore) *Controller {
|
||||
return NewController(config.Git.BaseURL, spaceCheck, authorizer, spaceStore, repoStore, principalStore)
|
||||
return NewController(urlProvider, spaceCheck, authorizer, spaceStore, repoStore, principalStore)
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@ import (
|
|||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/paths"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/rs/zerolog/hlog"
|
||||
|
@ -88,11 +89,12 @@ func GetInfoRefs(client gitrpc.Interface, repoStore store.RepoStore, authorizer
|
|||
}
|
||||
}
|
||||
|
||||
func GetUploadPack(client gitrpc.Interface, repoStore store.RepoStore, authorizer authz.Authorizer) http.HandlerFunc {
|
||||
func GetUploadPack(client gitrpc.Interface, urlProvider *url.Provider,
|
||||
repoStore store.RepoStore, authorizer authz.Authorizer) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
const service = "upload-pack"
|
||||
|
||||
if err := serviceRPC(w, r, client, repoStore, authorizer, service, false,
|
||||
if err := serviceRPC(w, r, client, urlProvider, repoStore, authorizer, service, false,
|
||||
enum.PermissionRepoView, true); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
|
@ -100,10 +102,11 @@ func GetUploadPack(client gitrpc.Interface, repoStore store.RepoStore, authorize
|
|||
}
|
||||
}
|
||||
|
||||
func PostReceivePack(client gitrpc.Interface, repoStore store.RepoStore, authorizer authz.Authorizer) http.HandlerFunc {
|
||||
func PostReceivePack(client gitrpc.Interface, urlProvider *url.Provider,
|
||||
repoStore store.RepoStore, authorizer authz.Authorizer) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
const service = "receive-pack"
|
||||
if err := serviceRPC(w, r, client, repoStore, authorizer, service, true,
|
||||
if err := serviceRPC(w, r, client, urlProvider, repoStore, authorizer, service, true,
|
||||
enum.PermissionRepoEdit, false); err != nil {
|
||||
var authError *GitAuthError
|
||||
if errors.As(err, &authError) {
|
||||
|
@ -120,6 +123,7 @@ func serviceRPC(
|
|||
w http.ResponseWriter,
|
||||
r *http.Request,
|
||||
client gitrpc.Interface,
|
||||
urlProvider *url.Provider,
|
||||
repoStore store.RepoStore,
|
||||
authorizer authz.Authorizer,
|
||||
service string,
|
||||
|
@ -180,7 +184,11 @@ func serviceRPC(
|
|||
|
||||
// setup read/writeparams depending on whether it's a write operation
|
||||
if isWriteOperation {
|
||||
writeParams := repoctrl.CreateRPCWriteParams(session, repo)
|
||||
var writeParams gitrpc.WriteParams
|
||||
writeParams, err = repoctrl.CreateRPCWriteParams(ctx, urlProvider, session, repo)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create RPC write params: %w", err)
|
||||
}
|
||||
params.WriteParams = &writeParams
|
||||
} else {
|
||||
readParams := repoctrl.CreateRPCReadParams(repo)
|
||||
|
|
|
@ -15,10 +15,10 @@ import (
|
|||
const BranchCreatedEvent events.EventType = "branchcreated"
|
||||
|
||||
type BranchCreatedPayload struct {
|
||||
RepoUID string `json:"repo_uid"`
|
||||
BranchName string `json:"branch_name"`
|
||||
FullRef string `json:"full_ref"`
|
||||
SHA string `json:"sha"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
PrincipalID int64 `json:"principal_id"`
|
||||
Ref string `json:"ref"`
|
||||
SHA string `json:"sha"`
|
||||
}
|
||||
|
||||
func (r *Reporter) BranchCreated(ctx context.Context, payload *BranchCreatedPayload) {
|
|
@ -15,10 +15,10 @@ import (
|
|||
const BranchDeletedEvent events.EventType = "branchdeleted"
|
||||
|
||||
type BranchDeletedPayload struct {
|
||||
RepoUID string `json:"repo_uid"`
|
||||
BranchName string `json:"branch_name"`
|
||||
FullRef string `json:"full_ref"`
|
||||
SHA string `json:"sha"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
PrincipalID int64 `json:"principal_id"`
|
||||
Ref string `json:"ref"`
|
||||
SHA string `json:"sha"`
|
||||
}
|
||||
|
||||
func (r *Reporter) BranchDeleted(ctx context.Context, payload *BranchDeletedPayload) {
|
|
@ -15,12 +15,12 @@ import (
|
|||
const BranchUpdatedEvent events.EventType = "branchupdated"
|
||||
|
||||
type BranchUpdatedPayload struct {
|
||||
RepoUID string `json:"repo_uid"`
|
||||
BranchName string `json:"branch_name"`
|
||||
FullRef string `json:"full_ref"`
|
||||
OldSHA string `json:"old_sha"`
|
||||
NewSHA string `json:"new_sha"`
|
||||
Forced bool `json:"forced"`
|
||||
RepoID int64 `json:"repo_id"`
|
||||
PrincipalID int64 `json:"principal_id"`
|
||||
Ref string `json:"ref"`
|
||||
OldSHA string `json:"old_sha"`
|
||||
NewSHA string `json:"new_sha"`
|
||||
// Forced bool `json:"forced"` TODO: data not available yet.
|
||||
}
|
||||
|
||||
func (r *Reporter) BranchUpdated(ctx context.Context, payload *BranchUpdatedPayload) {
|
|
@ -13,8 +13,13 @@ import (
|
|||
// WireSet provides a wire set for this package.
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideReaderFactory,
|
||||
ProvideReporter,
|
||||
)
|
||||
|
||||
func ProvideReaderFactory(eventsSystem *events.System) (*events.ReaderFactory[*Reader], error) {
|
||||
return NewReaderFactory(eventsSystem)
|
||||
}
|
||||
|
||||
func ProvideReporter(eventsSystem *events.System) (*Reporter, error) {
|
||||
return NewReporter(eventsSystem)
|
||||
}
|
|
@ -17,6 +17,7 @@ import (
|
|||
"github.com/harness/gitness/internal/auth/authn"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/go-chi/chi"
|
||||
|
@ -32,6 +33,7 @@ type GitHandler interface {
|
|||
// NewGitHandler returns a new GitHandler.
|
||||
func NewGitHandler(
|
||||
config *types.Config,
|
||||
urlProvider *url.Provider,
|
||||
repoStore store.RepoStore,
|
||||
authenticator authn.Authenticator,
|
||||
authorizer authz.Authorizer,
|
||||
|
@ -54,9 +56,8 @@ func NewGitHandler(
|
|||
r.Use(middlewareauthn.Attempt(authenticator))
|
||||
|
||||
// smart protocol
|
||||
r.Handle("/git-upload-pack", handlerrepo.GetUploadPack(client, repoStore, authorizer))
|
||||
|
||||
r.Post("/git-receive-pack", handlerrepo.PostReceivePack(client, repoStore, authorizer))
|
||||
r.Handle("/git-upload-pack", handlerrepo.GetUploadPack(client, urlProvider, repoStore, authorizer))
|
||||
r.Post("/git-receive-pack", handlerrepo.PostReceivePack(client, urlProvider, repoStore, authorizer))
|
||||
r.Get("/info/refs", handlerrepo.GetInfoRefs(client, repoStore, authorizer))
|
||||
|
||||
// dumb protocol
|
||||
|
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/harness/gitness/internal/auth/authn"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/google/wire"
|
||||
|
@ -38,12 +39,13 @@ func ProvideRouter(
|
|||
|
||||
func ProvideGitHandler(
|
||||
config *types.Config,
|
||||
urlProvider *url.Provider,
|
||||
repoStore store.RepoStore,
|
||||
authenticator authn.Authenticator,
|
||||
authorizer authz.Authorizer,
|
||||
client gitrpc.Interface,
|
||||
) GitHandler {
|
||||
return NewGitHandler(config, repoStore, authenticator, authorizer, client)
|
||||
return NewGitHandler(config, urlProvider, repoStore, authenticator, authorizer, client)
|
||||
}
|
||||
|
||||
func ProvideAPIHandler(
|
||||
|
@ -55,7 +57,8 @@ func ProvideAPIHandler(
|
|||
webhookCtrl *webhook.Controller,
|
||||
saCtrl *serviceaccount.Controller,
|
||||
userCtrl *user.Controller) APIHandler {
|
||||
return NewAPIHandler(config, authenticator, repoCtrl, spaceCtrl, pullreqCtrl, webhookCtrl, saCtrl, userCtrl)
|
||||
return NewAPIHandler(config, authenticator, repoCtrl, spaceCtrl, pullreqCtrl,
|
||||
webhookCtrl, saCtrl, userCtrl)
|
||||
}
|
||||
|
||||
func ProvideWebHandler(config *types.Config) WebHandler {
|
||||
|
|
|
@ -0,0 +1,49 @@
|
|||
// Copyright 2022 Harness Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Polyform Free Trial License
|
||||
// that can be found in the LICENSE.md file for this repository.
|
||||
|
||||
package url
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/url"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Provider provides the URLs of the gitness system.
|
||||
type Provider struct {
|
||||
// apiURLRaw stores the raw URL the api endpoints are available at.
|
||||
apiURLRaw string
|
||||
|
||||
// gitURL stores the URL the git endpoints are available at.
|
||||
// NOTE: we store it as url.URL so we can derive clone URLS without errors.
|
||||
gitURL *url.URL
|
||||
}
|
||||
|
||||
func NewProvider(apiURLRaw string, rawGitURL string) (*Provider, error) {
|
||||
gitURL, err := url.Parse(rawGitURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("provided rawGitURL '%s' is invalid: %w", rawGitURL, err)
|
||||
}
|
||||
|
||||
return &Provider{
|
||||
apiURLRaw: apiURLRaw,
|
||||
gitURL: gitURL,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// GetAPIBaseURL returns the base url of the api server.
|
||||
func (p *Provider) GetAPIBaseURL() string {
|
||||
return p.apiURLRaw
|
||||
}
|
||||
|
||||
// GenerateRepoCloneURL generates the git clone URL for the provided repo path.
|
||||
func (p *Provider) GenerateRepoCloneURL(repoPath string) string {
|
||||
repoPath = path.Clean(repoPath)
|
||||
if !strings.HasSuffix(repoPath, ".git") {
|
||||
repoPath += ".git"
|
||||
}
|
||||
|
||||
return p.gitURL.JoinPath(repoPath).String()
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2022 Harness Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Polyform Free Trial License
|
||||
// that can be found in the LICENSE.md file for this repository.
|
||||
|
||||
package url
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
||||
// WireSet provides a wire set for this package.
|
||||
var WireSet = wire.NewSet(ProvideURLProvider)
|
||||
|
||||
func ProvideURLProvider(config *types.Config) (*Provider, error) {
|
||||
return NewProvider(
|
||||
config.URL.API,
|
||||
config.URL.Git,
|
||||
)
|
||||
}
|
|
@ -8,82 +8,75 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/harness/gitness/events"
|
||||
gitevents "github.com/harness/gitness/gitrpc/events"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
gitevents "github.com/harness/gitness/internal/events/git"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// BranchBody describes the body of Branch related webhook triggers.
|
||||
// NOTE: Use a single payload format to make it easier for consumers!
|
||||
// TODO: move in separate package for small import?
|
||||
type BranchBody struct {
|
||||
Repo RepoMetadata `json:"repo"`
|
||||
Ref string `json:"ref"`
|
||||
Before string `json:"before"`
|
||||
After string `json:"after"`
|
||||
Forced bool `json:"forced"`
|
||||
Trigger enum.WebhookTrigger `json:"trigger"`
|
||||
Repo RepositoryInfo `json:"repo"`
|
||||
Principal PrincipalInfo `json:"principal"`
|
||||
Ref string `json:"ref"`
|
||||
Before string `json:"before"`
|
||||
After string `json:"after"`
|
||||
// Forced bool `json:"forced"` TODO: data has to be calculated explicitly
|
||||
}
|
||||
|
||||
func getEventHandlerForBranchCreated(server *Server,
|
||||
repoStore store.RepoStore) func(context.Context, *events.Event[*gitevents.BranchCreatedPayload]) error {
|
||||
return func(ctx context.Context, event *events.Event[*gitevents.BranchCreatedPayload]) error {
|
||||
return triggerForEventWithGitUID(ctx, server, repoStore, event.ID, event.Payload.RepoUID,
|
||||
enum.WebhookTriggerBranchPushed, func(repo *types.Repository) interface{} {
|
||||
return &BranchBody{
|
||||
Repo: RepoMetadata{
|
||||
ID: repo.ID,
|
||||
Path: repo.Path,
|
||||
UID: repo.UID,
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
GitURL: "", // TODO: GitURL has to be generated
|
||||
},
|
||||
Ref: event.Payload.FullRef,
|
||||
Before: types.NilSHA,
|
||||
After: event.Payload.SHA,
|
||||
}
|
||||
})
|
||||
}
|
||||
// handleEventBranchCreated handles branch created events
|
||||
// and triggers branch created webhooks for the source repo.
|
||||
func (s *Server) handleEventBranchCreated(ctx context.Context,
|
||||
event *events.Event[*gitevents.BranchCreatedPayload]) error {
|
||||
return s.triggerWebhooksForEventWithRepoAndPrincipal(ctx, enum.WebhookTriggerBranchCreated,
|
||||
event.ID, event.Payload.RepoID, event.Payload.PrincipalID,
|
||||
func(repo *types.Repository, principal *types.Principal) interface{} {
|
||||
return &BranchBody{
|
||||
Trigger: enum.WebhookTriggerBranchCreated,
|
||||
Repo: repositoryInfoFrom(repo, s.urlProvider),
|
||||
Principal: principalInfoFrom(principal),
|
||||
Ref: event.Payload.Ref,
|
||||
Before: types.NilSHA,
|
||||
After: event.Payload.SHA,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getEventHandlerForBranchUpdated(server *Server,
|
||||
repoStore store.RepoStore) func(context.Context, *events.Event[*gitevents.BranchUpdatedPayload]) error {
|
||||
return func(ctx context.Context, event *events.Event[*gitevents.BranchUpdatedPayload]) error {
|
||||
return triggerForEventWithGitUID(ctx, server, repoStore, event.ID, event.Payload.RepoUID,
|
||||
enum.WebhookTriggerBranchPushed, func(repo *types.Repository) interface{} {
|
||||
return &BranchBody{
|
||||
Repo: RepoMetadata{
|
||||
ID: repo.ID,
|
||||
Path: repo.Path,
|
||||
UID: repo.UID,
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
GitURL: "", // TODO: GitURL has to be generated
|
||||
},
|
||||
Ref: event.Payload.FullRef,
|
||||
Before: event.Payload.OldSHA,
|
||||
After: event.Payload.NewSHA,
|
||||
Forced: event.Payload.Forced,
|
||||
}
|
||||
})
|
||||
}
|
||||
// handleEventBranchUpdated handles branch updated events
|
||||
// and triggers branch updated webhooks for the source repo.
|
||||
func (s *Server) handleEventBranchUpdated(ctx context.Context,
|
||||
event *events.Event[*gitevents.BranchUpdatedPayload]) error {
|
||||
return s.triggerWebhooksForEventWithRepoAndPrincipal(ctx, enum.WebhookTriggerBranchUpdated,
|
||||
event.ID, event.Payload.RepoID, event.Payload.PrincipalID,
|
||||
func(repo *types.Repository, principal *types.Principal) interface{} {
|
||||
return &BranchBody{
|
||||
Trigger: enum.WebhookTriggerBranchUpdated,
|
||||
Repo: repositoryInfoFrom(repo, s.urlProvider),
|
||||
Principal: principalInfoFrom(principal),
|
||||
Ref: event.Payload.Ref,
|
||||
Before: event.Payload.OldSHA,
|
||||
After: event.Payload.NewSHA,
|
||||
// Forced: true/false, // TODO: data not available yet
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func getEventHandlerForBranchDeleted(server *Server,
|
||||
repoStore store.RepoStore) func(context.Context, *events.Event[*gitevents.BranchDeletedPayload]) error {
|
||||
return func(ctx context.Context, event *events.Event[*gitevents.BranchDeletedPayload]) error {
|
||||
return triggerForEventWithGitUID(ctx, server, repoStore, event.ID, event.Payload.RepoUID,
|
||||
enum.WebhookTriggerBranchDeleted, func(repo *types.Repository) interface{} {
|
||||
return &BranchBody{
|
||||
Repo: RepoMetadata{
|
||||
ID: repo.ID,
|
||||
Path: repo.Path,
|
||||
UID: repo.UID,
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
GitURL: "", // TODO: GitURL has to be generated
|
||||
},
|
||||
Ref: event.Payload.FullRef,
|
||||
Before: event.Payload.SHA,
|
||||
After: types.NilSHA,
|
||||
}
|
||||
})
|
||||
}
|
||||
// handleEventBranchDeleted handles branch deleted events
|
||||
// and triggers branch deleted webhooks for the source repo.
|
||||
func (s *Server) handleEventBranchDeleted(ctx context.Context,
|
||||
event *events.Event[*gitevents.BranchDeletedPayload]) error {
|
||||
return s.triggerWebhooksForEventWithRepoAndPrincipal(ctx, enum.WebhookTriggerBranchDeleted,
|
||||
event.ID, event.Payload.RepoID, event.Payload.PrincipalID,
|
||||
func(repo *types.Repository, principal *types.Principal) interface{} {
|
||||
return &BranchBody{
|
||||
Trigger: enum.WebhookTriggerBranchDeleted,
|
||||
Repo: repositoryInfoFrom(repo, s.urlProvider),
|
||||
Principal: principalInfoFrom(principal),
|
||||
Ref: event.Payload.Ref,
|
||||
Before: event.Payload.SHA,
|
||||
After: types.NilSHA,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// Copyright 2022 Harness Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Polyform Free Trial License
|
||||
// that can be found in the LICENSE.md file for this repository.
|
||||
|
||||
package webhook
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/internal/url"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
// RepositoryInfo describes the repo related info for a webhook payload.
|
||||
// NOTE: don't use types package as we want webhook payload to be independent from API calls.
|
||||
type RepositoryInfo struct {
|
||||
ID int64 `json:"id"`
|
||||
Path string `json:"path"`
|
||||
UID string `json:"uid"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
GitURL string `json:"git_url"`
|
||||
}
|
||||
|
||||
// repositoryInfoFrom gets the RespositoryInfo from a types.Repository.
|
||||
func repositoryInfoFrom(repo *types.Repository, urlProvider *url.Provider) RepositoryInfo {
|
||||
return RepositoryInfo{
|
||||
ID: repo.ID,
|
||||
Path: repo.Path,
|
||||
UID: repo.UID,
|
||||
DefaultBranch: repo.DefaultBranch,
|
||||
GitURL: urlProvider.GenerateRepoCloneURL(repo.Path),
|
||||
}
|
||||
}
|
||||
|
||||
// PrincipalInfo describes the principal related info for a webhook payload.
|
||||
// NOTE: don't use types package as we want webhook payload to be independent from API calls.
|
||||
type PrincipalInfo struct {
|
||||
ID int64 `json:"id"`
|
||||
UID string `json:"uid"`
|
||||
DisplayName string `json:"display_name"`
|
||||
Email string `json:"email"`
|
||||
}
|
||||
|
||||
// principalInfoFrom gets the PrincipalInfo from a types.Principal.
|
||||
func principalInfoFrom(principal *types.Principal) PrincipalInfo {
|
||||
return PrincipalInfo{
|
||||
ID: principal.ID,
|
||||
UID: principal.UID,
|
||||
DisplayName: principal.DisplayName,
|
||||
Email: principal.Email,
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/events"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
@ -21,32 +22,69 @@ func generateTriggerIDFromEventID(eventID string) string {
|
|||
return fmt.Sprintf("event-%s", eventID)
|
||||
}
|
||||
|
||||
func triggerForEventWithGitUID(ctx context.Context, server *Server, repoStore store.RepoStore, eventID string,
|
||||
repoGitUID string, triggerType enum.WebhookTrigger, createBody func(*types.Repository) interface{}) error {
|
||||
// TODO: can we avoid this DB call? would need the gitrpc to know the repo id though ...
|
||||
repo, err := repoStore.FindByGitUID(ctx, repoGitUID)
|
||||
|
||||
// not found error is unrecoverable - most likely a racing condition of repo being deleted by now
|
||||
if err != nil && errors.Is(err, store.ErrResourceNotFound) {
|
||||
log.Ctx(ctx).Warn().Err(err).
|
||||
Msgf("discard event since repo with gitUID '%s' doesn't exist anymore", repoGitUID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// all other errors we return and force the event to be reprocessed
|
||||
// triggerWebhooksForEventWithRepoAndPrincipal triggers all webhooks for the given repo and triggerType
|
||||
// using the eventID to generate a deterministic triggerID and using the output of bodyFn as payload.
|
||||
// The method tries to find the repository and principal and provides both to the bodyFn to generate the body.
|
||||
func (s *Server) triggerWebhooksForEventWithRepoAndPrincipal(ctx context.Context,
|
||||
triggerType enum.WebhookTrigger, eventID string, repoID int64, principalID int64,
|
||||
createBodyFn func(*types.Repository, *types.Principal) interface{}) error {
|
||||
// NOTE: technically we could avoid this call if we send the data via the event (though then events will get big)
|
||||
repo, err := s.findRepositoryForEvent(ctx, repoID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get repo for gitUID '%s': %w", repoGitUID, err)
|
||||
return err
|
||||
}
|
||||
|
||||
body := createBody(repo)
|
||||
return triggerForEvent(ctx, server, eventID, enum.WebhookParentRepo, repo.ID, triggerType, body)
|
||||
// NOTE: technically we could avoid this call if we send the data via the event (though then events will get big)
|
||||
principal, err := s.findPrincipalForEvent(ctx, principalID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// create body
|
||||
body := createBodyFn(repo, principal)
|
||||
|
||||
return s.triggerWebhooksForEvent(ctx, eventID, enum.WebhookParentRepo, repo.ID, triggerType, body)
|
||||
}
|
||||
|
||||
func triggerForEvent(ctx context.Context, server *Server, eventID string,
|
||||
// findRepositoryForEvent finds the repository for the provided repoID.
|
||||
func (s *Server) findRepositoryForEvent(ctx context.Context, repoID int64) (*types.Repository, error) {
|
||||
repo, err := s.repoStore.Find(ctx, repoID)
|
||||
|
||||
if err != nil && errors.Is(err, store.ErrResourceNotFound) {
|
||||
// not found error is unrecoverable - most likely a racing condition of repo being deleted by now
|
||||
return nil, events.NewDiscardEventErrorf("repo with id '%d' doesn't exist anymore", repoID)
|
||||
}
|
||||
if err != nil {
|
||||
// all other errors we return and force the event to be reprocessed
|
||||
return nil, fmt.Errorf("failed to get repo for id '%d': %w", repoID, err)
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
// findPrincipalForEvent finds the principal for the provided principalID.
|
||||
func (s *Server) findPrincipalForEvent(ctx context.Context, principalID int64) (*types.Principal, error) {
|
||||
principal, err := s.principalStore.Find(ctx, principalID)
|
||||
|
||||
if err != nil && errors.Is(err, store.ErrResourceNotFound) {
|
||||
// this should never happen (as we won't delete principals) - discard event
|
||||
return nil, events.NewDiscardEventErrorf("principal with id '%d' doesn't exist anymore", principalID)
|
||||
}
|
||||
if err != nil {
|
||||
// all other errors we return and force the event to be reprocessed
|
||||
return nil, fmt.Errorf("failed to get principal for id '%d': %w", principalID, err)
|
||||
}
|
||||
|
||||
return principal, nil
|
||||
}
|
||||
|
||||
// triggerWebhooksForEvent triggers all webhooks for the given parentType/ID and triggerType
|
||||
// using the eventID to generate a deterministic triggerID and sending the provided body as payload.
|
||||
func (s *Server) triggerWebhooksForEvent(ctx context.Context, eventID string,
|
||||
parentType enum.WebhookParent, parentID int64, triggerType enum.WebhookTrigger, body interface{}) error {
|
||||
triggerID := generateTriggerIDFromEventID(eventID)
|
||||
|
||||
results, err := server.triggerWebhooksFor(ctx, parentType, parentID, triggerID, triggerType, body)
|
||||
results, err := s.triggerWebhooksFor(ctx, parentType, parentID, triggerID, triggerType, body)
|
||||
|
||||
// return all errors and force the event to be reprocessed (it's not webhook execution specific!)
|
||||
if err != nil {
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
// Copyright 2022 Harness Inc. All rights reserved.
|
||||
// Use of this source code is governed by the Polyform Free Trial License
|
||||
// that can be found in the LICENSE.md file for this repository.
|
||||
|
||||
package webhook
|
||||
|
||||
// RepoMetadata describes the repo related metadata of webhook payload.
|
||||
// TODO: move in separate package for small import?
|
||||
type RepoMetadata struct {
|
||||
ID int64 `json:"id"`
|
||||
Path string `json:"path"`
|
||||
UID string `json:"uid"`
|
||||
DefaultBranch string `json:"default_branch"`
|
||||
GitURL string `json:"git_url,omitempty"` // TODO: remove once handled properly.
|
||||
}
|
|
@ -11,8 +11,9 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/harness/gitness/events"
|
||||
gitevents "github.com/harness/gitness/gitrpc/events"
|
||||
gitevents "github.com/harness/gitness/internal/events/git"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -32,6 +33,9 @@ type Config struct {
|
|||
type Server struct {
|
||||
webhookStore store.WebhookStore
|
||||
webhookExecutionStore store.WebhookExecutionStore
|
||||
urlProvider *url.Provider
|
||||
repoStore store.RepoStore
|
||||
principalStore store.PrincipalStore
|
||||
|
||||
readerCanceler *events.ReaderCanceler
|
||||
secureHTTPClient *http.Client
|
||||
|
@ -41,16 +45,20 @@ type Server struct {
|
|||
func NewServer(ctx context.Context, config Config,
|
||||
gitReaderFactory *events.ReaderFactory[*gitevents.Reader],
|
||||
webhookStore store.WebhookStore, webhookExecutionStore store.WebhookExecutionStore,
|
||||
repoStore store.RepoStore) (*Server, error) {
|
||||
repoStore store.RepoStore, urlProvider *url.Provider,
|
||||
principalStore store.PrincipalStore) (*Server, error) {
|
||||
server := &Server{
|
||||
webhookStore: webhookStore,
|
||||
webhookExecutionStore: webhookExecutionStore,
|
||||
repoStore: repoStore,
|
||||
urlProvider: urlProvider,
|
||||
principalStore: principalStore,
|
||||
|
||||
// set after launching factory
|
||||
readerCanceler: nil,
|
||||
|
||||
secureHTTPClient: newHTTPClient(config.AllowLoopback, config.AllowPrivateNetwork, false),
|
||||
insecureHTTPClient: newHTTPClient(config.AllowLoopback, config.AllowPrivateNetwork, true),
|
||||
|
||||
webhookStore: webhookStore,
|
||||
webhookExecutionStore: webhookExecutionStore,
|
||||
}
|
||||
canceler, err := gitReaderFactory.Launch(ctx, eventsReaderGroupName, config.EventReaderName,
|
||||
func(r *gitevents.Reader) error {
|
||||
|
@ -60,9 +68,9 @@ func NewServer(ctx context.Context, config Config,
|
|||
_ = r.SetProcessingTimeout(processingTimeout)
|
||||
|
||||
// register events
|
||||
_ = r.RegisterBranchCreated(getEventHandlerForBranchCreated(server, repoStore))
|
||||
_ = r.RegisterBranchDeleted(getEventHandlerForBranchDeleted(server, repoStore))
|
||||
_ = r.RegisterBranchUpdated(getEventHandlerForBranchUpdated(server, repoStore))
|
||||
_ = r.RegisterBranchCreated(server.handleEventBranchCreated)
|
||||
_ = r.RegisterBranchUpdated(server.handleEventBranchUpdated)
|
||||
_ = r.RegisterBranchDeleted(server.handleEventBranchDeleted)
|
||||
|
||||
return nil
|
||||
})
|
||||
|
|
|
@ -8,8 +8,9 @@ import (
|
|||
"context"
|
||||
|
||||
"github.com/harness/gitness/events"
|
||||
gitevents "github.com/harness/gitness/gitrpc/events"
|
||||
gitevents "github.com/harness/gitness/internal/events/git"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/internal/url"
|
||||
|
||||
"github.com/google/wire"
|
||||
)
|
||||
|
@ -22,6 +23,8 @@ var WireSet = wire.NewSet(
|
|||
func ProvideServer(ctx context.Context, config Config,
|
||||
gitReaderFactory *events.ReaderFactory[*gitevents.Reader],
|
||||
webhookStore store.WebhookStore, webhookExecutionStore store.WebhookExecutionStore,
|
||||
repoStore store.RepoStore) (*Server, error) {
|
||||
return NewServer(ctx, config, gitReaderFactory, webhookStore, webhookExecutionStore, repoStore)
|
||||
repoStore store.RepoStore, urlProvider *url.Provider,
|
||||
principalStore store.PrincipalStore) (*Server, error) {
|
||||
return NewServer(ctx, config, gitReaderFactory, webhookStore, webhookExecutionStore,
|
||||
repoStore, urlProvider, principalStore)
|
||||
}
|
||||
|
|
|
@ -16,9 +16,14 @@ type Config struct {
|
|||
Debug bool `envconfig:"GITNESS_DEBUG"`
|
||||
Trace bool `envconfig:"GITNESS_TRACE"`
|
||||
|
||||
// URL defines the URLs via which the different parts of the service are reachable by.
|
||||
URL struct {
|
||||
Git string `envconfig:"GITNESS_URL_GIT" default:"http://localhost:3000"`
|
||||
API string `envconfig:"GITNESS_URL_API" default:"http://localhost:3000"`
|
||||
}
|
||||
|
||||
// Git defines the git configuration parameters
|
||||
Git struct {
|
||||
BaseURL string `envconfig:"GITNESS_GIT_BASE_URL" default:"http://localhost:3000"` // clone url
|
||||
Root string `envconfig:"GITNESS_GIT_ROOT"`
|
||||
TmpDir string `envconfig:"GITNESS_GIT_TMP_DIR"` // directory for temporary data (repo clone)
|
||||
ServerHookPath string `envconfig:"GITNESS_GIT_SERVER_HOOK_PATH"` // path to binary used as git server hook
|
||||
|
|
|
@ -51,15 +51,18 @@ func GetAllWebhookExecutionResults() []WebhookExecutionResult {
|
|||
type WebhookTrigger string
|
||||
|
||||
const (
|
||||
// WebhookTriggerBranchPushed gets triggered when a branch gets pushed (created or updated).
|
||||
WebhookTriggerBranchPushed WebhookTrigger = "branch_pushed"
|
||||
// WebhookTriggerBranchCreated gets triggered when a branch gets created.
|
||||
WebhookTriggerBranchCreated WebhookTrigger = "branch_created"
|
||||
// WebhookTriggerBranchUpdated gets triggered when a branch gets updated.
|
||||
WebhookTriggerBranchUpdated WebhookTrigger = "branch_updated"
|
||||
// WebhookTriggerBranchDeleted gets triggered when a branch gets deleted.
|
||||
WebhookTriggerBranchDeleted WebhookTrigger = "branch_deleted"
|
||||
)
|
||||
|
||||
func GetAllWebhookTriggers() []WebhookTrigger {
|
||||
return []WebhookTrigger{
|
||||
WebhookTriggerBranchPushed,
|
||||
WebhookTriggerBranchCreated,
|
||||
WebhookTriggerBranchUpdated,
|
||||
WebhookTriggerBranchDeleted,
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue