Update default branch on empty repo for first commit (#1122)

This commit is contained in:
Atefeh Mohseni-Ejiyeh 2024-04-04 01:16:43 +00:00 committed by Harness
parent 47f4070b3c
commit b64f4c41fa
35 changed files with 643 additions and 269 deletions

View File

@ -19,7 +19,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"github.com/harness/gitness/app/api/controller/githook" "github.com/harness/gitness/app/githook"
"github.com/harness/gitness/git" "github.com/harness/gitness/git"
"github.com/harness/gitness/git/hook" "github.com/harness/gitness/git/hook"
"github.com/harness/gitness/store" "github.com/harness/gitness/store"
@ -33,12 +33,12 @@ var _ hook.Client = (*ControllerClient)(nil)
// ControllerClientFactory creates clients that directly call the controller to execute githooks. // ControllerClientFactory creates clients that directly call the controller to execute githooks.
type ControllerClientFactory struct { type ControllerClientFactory struct {
githookCtrl *githook.Controller githookCtrl *Controller
git git.Interface git git.Interface
} }
func (f *ControllerClientFactory) NewClient(_ context.Context, envVars map[string]string) (hook.Client, error) { func (f *ControllerClientFactory) NewClient(_ context.Context, envVars map[string]string) (hook.Client, error) {
payload, err := hook.LoadPayloadFromMap[Payload](envVars) payload, err := hook.LoadPayloadFromMap[githook.Payload](envVars)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to load payload from provided map of environment variables: %w", err) return nil, fmt.Errorf("failed to load payload from provided map of environment variables: %w", err)
} }
@ -53,7 +53,7 @@ func (f *ControllerClientFactory) NewClient(_ context.Context, envVars map[strin
} }
return &ControllerClient{ return &ControllerClient{
baseInput: GetInputBaseFromPayload(payload), baseInput: githook.GetInputBaseFromPayload(payload),
githookCtrl: f.githookCtrl, githookCtrl: f.githookCtrl,
git: f.git, git: f.git,
}, nil }, nil
@ -62,8 +62,8 @@ func (f *ControllerClientFactory) NewClient(_ context.Context, envVars map[strin
// ControllerClient directly calls the controller to execute githooks. // ControllerClient directly calls the controller to execute githooks.
type ControllerClient struct { type ControllerClient struct {
baseInput types.GithookInputBase baseInput types.GithookInputBase
githookCtrl *githook.Controller githookCtrl *Controller
git githook.RestrictedGIT git RestrictedGIT
} }
func (c *ControllerClient) PreReceive( func (c *ControllerClient) PreReceive(

View File

@ -23,6 +23,7 @@ import (
"github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth"
"github.com/harness/gitness/app/auth/authz" "github.com/harness/gitness/app/auth/authz"
eventsgit "github.com/harness/gitness/app/events/git" eventsgit "github.com/harness/gitness/app/events/git"
eventsrepo "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/services/settings"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
@ -41,6 +42,8 @@ type Controller struct {
principalStore store.PrincipalStore principalStore store.PrincipalStore
repoStore store.RepoStore repoStore store.RepoStore
gitReporter *eventsgit.Reporter gitReporter *eventsgit.Reporter
repoReporter *eventsrepo.Reporter
git git.Interface
pullreqStore store.PullReqStore pullreqStore store.PullReqStore
urlProvider url.Provider urlProvider url.Provider
protectionManager *protection.Manager protectionManager *protection.Manager
@ -56,6 +59,8 @@ func NewController(
principalStore store.PrincipalStore, principalStore store.PrincipalStore,
repoStore store.RepoStore, repoStore store.RepoStore,
gitReporter *eventsgit.Reporter, gitReporter *eventsgit.Reporter,
repoReporter *eventsrepo.Reporter,
git git.Interface,
pullreqStore store.PullReqStore, pullreqStore store.PullReqStore,
urlProvider url.Provider, urlProvider url.Provider,
protectionManager *protection.Manager, protectionManager *protection.Manager,
@ -64,13 +69,14 @@ func NewController(
preReceiveExtender PreReceiveExtender, preReceiveExtender PreReceiveExtender,
updateExtender UpdateExtender, updateExtender UpdateExtender,
postReceiveExtender PostReceiveExtender, postReceiveExtender PostReceiveExtender,
) *Controller { ) *Controller {
return &Controller{ return &Controller{
authorizer: authorizer, authorizer: authorizer,
principalStore: principalStore, principalStore: principalStore,
repoStore: repoStore, repoStore: repoStore,
gitReporter: gitReporter, gitReporter: gitReporter,
repoReporter: repoReporter,
git: git,
pullreqStore: pullreqStore, pullreqStore: pullreqStore,
urlProvider: urlProvider, urlProvider: urlProvider,
protectionManager: protectionManager, protectionManager: protectionManager,

View File

@ -19,13 +19,17 @@ import (
"fmt" "fmt"
"strings" "strings"
"github.com/harness/gitness/app/api/usererror"
"github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth"
"github.com/harness/gitness/app/bootstrap"
events "github.com/harness/gitness/app/events/git" events "github.com/harness/gitness/app/events/git"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/git" "github.com/harness/gitness/git"
"github.com/harness/gitness/git/hook" "github.com/harness/gitness/git/hook"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
"github.com/gotidy/ptr"
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
@ -51,13 +55,16 @@ func (c *Controller) PostReceive(
if err != nil { if err != nil {
return hook.Output{}, err return hook.Output{}, err
} }
// create output object and have following messages fill its messages
out := hook.Output{}
// update default branch based on ref update info on empty repos.
// as the branch could be different than the configured default value.
c.handleEmptyRepoPush(ctx, repo, in.PostReceiveInput, &out)
// report ref events (best effort) // report ref events (best effort)
c.reportReferenceEvents(ctx, rgit, repo, in.PrincipalID, in.PostReceiveInput) c.reportReferenceEvents(ctx, rgit, repo, in.PrincipalID, in.PostReceiveInput)
// create output object and have following messages fill its messages
out := hook.Output{}
// handle branch updates related to PRs - best effort // handle branch updates related to PRs - best effort
c.handlePRMessaging(ctx, repo, in.PostReceiveInput, &out) c.handlePRMessaging(ctx, repo, in.PostReceiveInput, &out)
@ -250,3 +257,50 @@ func (c *Controller) suggestPullRequest(
" "+c.urlProvider.GenerateUICompareURL(repo.Path, repo.DefaultBranch, branchName), " "+c.urlProvider.GenerateUICompareURL(repo.Path, repo.DefaultBranch, branchName),
) )
} }
// handleEmptyRepoPush updates repo default branch on empty repos if push contains branches.
func (c *Controller) handleEmptyRepoPush(
ctx context.Context,
repo *types.Repository,
in hook.PostReceiveInput,
out *hook.Output,
) {
if !repo.IsEmpty {
return
}
var branchName string
// we only care about one active branch that was pushed.
for _, refUpdate := range in.RefUpdates {
if strings.HasPrefix(refUpdate.Ref, gitReferenceNamePrefixBranch) &&
refUpdate.New.String() != types.NilSHA {
branchName = refUpdate.Ref[len(gitReferenceNamePrefixBranch):]
break
}
}
if branchName == "" {
out.Error = ptr.String(usererror.ErrEmptyRepoNeedsBranch.Error())
return
}
oldName := repo.DefaultBranch
var err error
repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error {
r.IsEmpty = false
r.DefaultBranch = branchName
return nil
})
if err != nil {
log.Ctx(ctx).Warn().Err(err).Msgf("failed to update the repo default branch to %s and is_empty to false", branchName)
return
}
if repo.DefaultBranch != oldName {
c.repoReporter.DefaultBranchUpdated(ctx, &repoevents.DefaultBranchUpdatedPayload{
RepoID: repo.ID,
PrincipalID: bootstrap.NewSystemServiceSession().Principal.ID,
OldName: oldName,
NewName: repo.DefaultBranch,
})
}
}

View File

@ -14,11 +14,76 @@
package githook package githook
import "github.com/google/wire" import (
"github.com/harness/gitness/app/api/controller/limiter"
"github.com/harness/gitness/app/auth/authz"
eventsgit "github.com/harness/gitness/app/events/git"
eventsrepo "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/settings"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/app/url"
"github.com/harness/gitness/git"
"github.com/harness/gitness/git/hook"
// Due to cyclic injection dependencies, wiring can be found at app/githook/wire.go "github.com/google/wire"
)
var WireSet = wire.NewSet( var WireSet = wire.NewSet(
ProvideController,
ProvideFactory,
)
func ProvideFactory() hook.ClientFactory {
return &ControllerClientFactory{
githookCtrl: nil,
}
}
func ProvideController(
authorizer authz.Authorizer,
principalStore store.PrincipalStore,
repoStore store.RepoStore,
gitReporter *eventsgit.Reporter,
repoReporter *eventsrepo.Reporter,
git git.Interface,
pullreqStore store.PullReqStore,
urlProvider url.Provider,
protectionManager *protection.Manager,
githookFactory hook.ClientFactory,
limiter limiter.ResourceLimiter,
settings *settings.Service,
preReceiveExtender PreReceiveExtender,
updateExtender UpdateExtender,
postReceiveExtender PostReceiveExtender,
) *Controller {
ctrl := NewController(
authorizer,
principalStore,
repoStore,
gitReporter,
repoReporter,
git,
pullreqStore,
urlProvider,
protectionManager,
limiter,
settings,
preReceiveExtender,
updateExtender,
postReceiveExtender,
)
// TODO: improve wiring if possible
if fct, ok := githookFactory.(*ControllerClientFactory); ok {
fct.githookCtrl = ctrl
fct.git = git
}
return ctrl
}
var ExtenderWireSet = wire.NewSet(
ProvidePreReceiveExtender, ProvidePreReceiveExtender,
ProvideUpdateExtender, ProvideUpdateExtender,
ProvidePostReceiveExtender, ProvidePostReceiveExtender,

View File

@ -25,6 +25,7 @@ import (
pullreqevents "github.com/harness/gitness/app/events/pullreq" pullreqevents "github.com/harness/gitness/app/events/pullreq"
"github.com/harness/gitness/app/services/codecomments" "github.com/harness/gitness/app/services/codecomments"
"github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/codeowners"
locker "github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/services/pullreq"
"github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/sse"
@ -33,7 +34,6 @@ import (
"github.com/harness/gitness/errors" "github.com/harness/gitness/errors"
"github.com/harness/gitness/git" "github.com/harness/gitness/git"
gitenum "github.com/harness/gitness/git/enum" gitenum "github.com/harness/gitness/git/enum"
"github.com/harness/gitness/lock"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
@ -55,12 +55,12 @@ type Controller struct {
checkStore store.CheckStore checkStore store.CheckStore
git git.Interface git git.Interface
eventReporter *pullreqevents.Reporter eventReporter *pullreqevents.Reporter
mtxManager lock.MutexManager
codeCommentMigrator *codecomments.Migrator codeCommentMigrator *codecomments.Migrator
pullreqService *pullreq.Service pullreqService *pullreq.Service
protectionManager *protection.Manager protectionManager *protection.Manager
sseStreamer sse.Streamer sseStreamer sse.Streamer
codeOwners *codeowners.Service codeOwners *codeowners.Service
locker *locker.Locker
} }
func NewController( func NewController(
@ -79,12 +79,12 @@ func NewController(
checkStore store.CheckStore, checkStore store.CheckStore,
git git.Interface, git git.Interface,
eventReporter *pullreqevents.Reporter, eventReporter *pullreqevents.Reporter,
mtxManager lock.MutexManager,
codeCommentMigrator *codecomments.Migrator, codeCommentMigrator *codecomments.Migrator,
pullreqService *pullreq.Service, pullreqService *pullreq.Service,
protectionManager *protection.Manager, protectionManager *protection.Manager,
sseStreamer sse.Streamer, sseStreamer sse.Streamer,
codeowners *codeowners.Service, codeowners *codeowners.Service,
locker *locker.Locker,
) *Controller { ) *Controller {
return &Controller{ return &Controller{
tx: tx, tx: tx,
@ -103,11 +103,11 @@ func NewController(
git: git, git: git,
codeCommentMigrator: codeCommentMigrator, codeCommentMigrator: codeCommentMigrator,
eventReporter: eventReporter, eventReporter: eventReporter,
mtxManager: mtxManager,
pullreqService: pullreqService, pullreqService: pullreqService,
protectionManager: protectionManager, protectionManager: protectionManager,
sseStreamer: sseStreamer, sseStreamer: sseStreamer,
codeOwners: codeowners, codeOwners: codeowners,
locker: locker,
} }
} }

View File

@ -1,83 +0,0 @@
// 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 pullreq
import (
"context"
"fmt"
"strconv"
"time"
"github.com/harness/gitness/contextutil"
"github.com/harness/gitness/lock"
"github.com/harness/gitness/logging"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
)
func (c *Controller) lockPR(
ctx context.Context,
repoID int64,
prNum int64,
expiry time.Duration,
) (func(), error) {
key := fmt.Sprintf("%d/pulls", repoID)
if prNum != 0 {
key += "/" + strconv.FormatInt(prNum, 10)
}
// annotate logs for easier debugging of lock related merge issues
// TODO: refactor once common logging annotations are added
ctx = logging.NewContext(ctx, func(c zerolog.Context) zerolog.Context {
return c.
Str("pullreq_lock", key).
Int64("repo_id", repoID)
})
mutex, err := c.mtxManager.NewMutex(
key,
lock.WithNamespace("repo"),
lock.WithExpiry(expiry),
lock.WithTimeoutFactor(4/expiry.Seconds()), // 4s
)
if err != nil {
return nil, fmt.Errorf("failed to create new mutex for pr %d in repo %d: %w", prNum, repoID, err)
}
err = mutex.Lock(ctx)
if err != nil {
return nil, fmt.Errorf("failed to lock mutex for pr %d in repo %d: %w", prNum, repoID, err)
}
log.Ctx(ctx).Debug().Msgf("successfully locked PR (expiry: %s)", expiry)
unlockFn := func() {
// always unlock independent of whether source context got canceled or not
ctx, cancel := context.WithTimeout(
contextutil.WithNewValues(context.Background(), ctx),
30*time.Second,
)
defer cancel()
err := mutex.Unlock(ctx)
if err != nil {
log.Ctx(ctx).Warn().Err(err).Msg("failed to unlock PR")
} else {
log.Ctx(ctx).Debug().Msg("successfully unlocked PR")
}
}
return unlockFn, nil
}

View File

@ -117,7 +117,7 @@ func (c *Controller) Merge(
// first one and second one will wait, when first one is done then second one // first one and second one will wait, when first one is done then second one
// continue with latest data from db with state merged and return error that // continue with latest data from db with state merged and return error that
// pr is already merged. // pr is already merged.
unlock, err := c.lockPR( unlock, err := c.locker.LockPR(
ctx, ctx,
targetRepo.ID, targetRepo.ID,
0, // 0 means locks all PRs for this repo 0, // 0 means locks all PRs for this repo

View File

@ -19,13 +19,13 @@ import (
pullreqevents "github.com/harness/gitness/app/events/pullreq" pullreqevents "github.com/harness/gitness/app/events/pullreq"
"github.com/harness/gitness/app/services/codecomments" "github.com/harness/gitness/app/services/codecomments"
"github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/codeowners"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/services/pullreq"
"github.com/harness/gitness/app/sse" "github.com/harness/gitness/app/sse"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/app/url" "github.com/harness/gitness/app/url"
"github.com/harness/gitness/git" "github.com/harness/gitness/git"
"github.com/harness/gitness/lock"
"github.com/harness/gitness/store/database/dbtx" "github.com/harness/gitness/store/database/dbtx"
"github.com/google/wire" "github.com/google/wire"
@ -43,10 +43,9 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer
repoStore store.RepoStore, principalStore store.PrincipalStore, repoStore store.RepoStore, principalStore store.PrincipalStore,
fileViewStore store.PullReqFileViewStore, membershipStore store.MembershipStore, fileViewStore store.PullReqFileViewStore, membershipStore store.MembershipStore,
checkStore store.CheckStore, checkStore store.CheckStore,
rpcClient git.Interface, eventReporter *pullreqevents.Reporter, rpcClient git.Interface, eventReporter *pullreqevents.Reporter, codeCommentMigrator *codecomments.Migrator,
mtxManager lock.MutexManager, codeCommentMigrator *codecomments.Migrator,
pullreqService *pullreq.Service, ruleManager *protection.Manager, sseStreamer sse.Streamer, pullreqService *pullreq.Service, ruleManager *protection.Manager, sseStreamer sse.Streamer,
codeOwners *codeowners.Service, codeOwners *codeowners.Service, locker *locker.Locker,
) *Controller { ) *Controller {
return NewController(tx, urlProvider, authorizer, return NewController(tx, urlProvider, authorizer,
pullReqStore, pullReqActivityStore, pullReqStore, pullReqActivityStore,
@ -56,6 +55,6 @@ func ProvideController(tx dbtx.Transactor, urlProvider url.Provider, authorizer
fileViewStore, membershipStore, fileViewStore, membershipStore,
checkStore, checkStore,
rpcClient, eventReporter, rpcClient, eventReporter,
mtxManager, codeCommentMigrator, codeCommentMigrator,
pullreqService, ruleManager, sseStreamer, codeOwners) pullreqService, ruleManager, sseStreamer, codeOwners, locker)
} }

View File

@ -29,6 +29,7 @@ import (
"github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/codeowners"
"github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/importer"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/services/settings"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
@ -66,6 +67,7 @@ type Controller struct {
eventReporter *repoevents.Reporter eventReporter *repoevents.Reporter
indexer keywordsearch.Indexer indexer keywordsearch.Indexer
resourceLimiter limiter.ResourceLimiter resourceLimiter limiter.ResourceLimiter
locker *locker.Locker
mtxManager lock.MutexManager mtxManager lock.MutexManager
identifierCheck check.RepoIdentifier identifierCheck check.RepoIdentifier
repoCheck Check repoCheck Check
@ -90,6 +92,7 @@ func NewController(
eventReporter *repoevents.Reporter, eventReporter *repoevents.Reporter,
indexer keywordsearch.Indexer, indexer keywordsearch.Indexer,
limiter limiter.ResourceLimiter, limiter limiter.ResourceLimiter,
locker *locker.Locker,
mtxManager lock.MutexManager, mtxManager lock.MutexManager,
identifierCheck check.RepoIdentifier, identifierCheck check.RepoIdentifier,
repoCheck Check, repoCheck Check,
@ -114,6 +117,7 @@ func NewController(
eventReporter: eventReporter, eventReporter: eventReporter,
indexer: indexer, indexer: indexer,
resourceLimiter: limiter, resourceLimiter: limiter,
locker: locker,
mtxManager: mtxManager, mtxManager: mtxManager,
identifierCheck: identifierCheck, identifierCheck: identifierCheck,
repoCheck: repoCheck, repoCheck: repoCheck,

View File

@ -81,7 +81,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
return fmt.Errorf("resource limit exceeded: %w", limiter.ErrMaxNumReposReached) return fmt.Errorf("resource limit exceeded: %w", limiter.ErrMaxNumReposReached)
} }
gitResp, err := c.createGitRepository(ctx, session, in) gitResp, isEmpty, err := c.createGitRepository(ctx, session, in)
if err != nil { if err != nil {
return fmt.Errorf("error creating repository on git: %w", err) return fmt.Errorf("error creating repository on git: %w", err)
} }
@ -99,6 +99,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
Updated: now, Updated: now,
ForkID: in.ForkID, ForkID: in.ForkID,
DefaultBranch: in.DefaultBranch, DefaultBranch: in.DefaultBranch,
IsEmpty: isEmpty,
} }
err = c.repoStore.Create(ctx, repo) err = c.repoStore.Create(ctx, repo)
if err != nil { if err != nil {
@ -118,7 +119,7 @@ func (c *Controller) Create(ctx context.Context, session *auth.Session, in *Crea
repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path) repo.GitURL = c.urlProvider.GenerateGITCloneURL(repo.Path)
// index repository if files are created // index repository if files are created
if in.Readme || in.GitIgnore != "" || (in.License != "" && in.License != "none") { if !repo.IsEmpty {
err = c.indexer.Index(ctx, repo) err = c.indexer.Index(ctx, repo)
if err != nil { if err != nil {
log.Ctx(ctx).Warn().Err(err).Int64("repo_id", repo.ID).Msg("failed to index repo") log.Ctx(ctx).Warn().Err(err).Int64("repo_id", repo.ID).Msg("failed to index repo")
@ -186,7 +187,7 @@ func (c *Controller) sanitizeCreateInput(in *CreateInput) error {
} }
func (c *Controller) createGitRepository(ctx context.Context, session *auth.Session, func (c *Controller) createGitRepository(ctx context.Context, session *auth.Session,
in *CreateInput) (*git.CreateRepositoryOutput, error) { in *CreateInput) (*git.CreateRepositoryOutput, bool, error) {
var ( var (
err error err error
content []byte content []byte
@ -202,7 +203,7 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess
if in.License != "" && in.License != "none" { if in.License != "" && in.License != "none" {
content, err = resources.ReadLicense(in.License) content, err = resources.ReadLicense(in.License)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read license '%s': %w", in.License, err) return nil, false, fmt.Errorf("failed to read license '%s': %w", in.License, err)
} }
files = append(files, git.File{ files = append(files, git.File{
Path: "LICENSE", Path: "LICENSE",
@ -212,7 +213,7 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess
if in.GitIgnore != "" { if in.GitIgnore != "" {
content, err = resources.ReadGitIgnore(in.GitIgnore) content, err = resources.ReadGitIgnore(in.GitIgnore)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to read git ignore '%s': %w", in.GitIgnore, err) return nil, false, fmt.Errorf("failed to read git ignore '%s': %w", in.GitIgnore, err)
} }
files = append(files, git.File{ files = append(files, git.File{
Path: ".gitignore", Path: ".gitignore",
@ -230,7 +231,7 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess
true, true,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to generate git hook environment variables: %w", err) return nil, false, fmt.Errorf("failed to generate git hook environment variables: %w", err)
} }
actor := identityFromPrincipal(session.Principal) actor := identityFromPrincipal(session.Principal)
@ -247,10 +248,10 @@ func (c *Controller) createGitRepository(ctx context.Context, session *auth.Sess
CommitterDate: &now, CommitterDate: &now,
}) })
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create repo on: %w", err) return nil, false, fmt.Errorf("failed to create repo on: %w", err)
} }
return resp, nil return resp, len(files) == 0, nil
} }
func createReadme(name, description string) []byte { func createReadme(name, description string) []byte {

View File

@ -21,12 +21,12 @@ import (
"github.com/harness/gitness/app/api/controller" "github.com/harness/gitness/app/api/controller"
"github.com/harness/gitness/app/auth" "github.com/harness/gitness/app/auth"
"github.com/harness/gitness/app/bootstrap"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/contextutil" "github.com/harness/gitness/contextutil"
"github.com/harness/gitness/git" "github.com/harness/gitness/git"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
"github.com/rs/zerolog/log"
) )
type UpdateDefaultBranchInput struct { type UpdateDefaultBranchInput struct {
@ -50,11 +50,11 @@ func (c *Controller) UpdateDefaultBranch(
// lock concurrent requests for updating the default branch of a repo // lock concurrent requests for updating the default branch of a repo
// requests will wait for previous ones to compelete before proceed // requests will wait for previous ones to compelete before proceed
unlock, err := c.lockDefaultBranch( unlock, err := c.locker.LockDefaultBranch(
ctx, ctx,
repo.GitUID, repo.ID,
in.Name, // branch name only used for logging (lock is on repo) in.Name, // branch name only used for logging (lock is on repo)
timeout+30*time.Second, timeout+30*time.Second, // add 30s to the lock to give enough time for updating default branch
) )
if err != nil { if err != nil {
return nil, err return nil, err
@ -82,6 +82,7 @@ func (c *Controller) UpdateDefaultBranch(
return nil, fmt.Errorf("failed to update the repo default branch: %w", err) return nil, fmt.Errorf("failed to update the repo default branch: %w", err)
} }
oldName := repo.DefaultBranch
repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error { repo, err = c.repoStore.UpdateOptLock(ctx, repo, func(r *types.Repository) error {
r.DefaultBranch = in.Name r.DefaultBranch = in.Name
return nil return nil
@ -90,11 +91,12 @@ func (c *Controller) UpdateDefaultBranch(
return nil, fmt.Errorf("failed to update the repo default branch on db:%w", err) return nil, fmt.Errorf("failed to update the repo default branch on db:%w", err)
} }
err = c.indexer.Index(ctx, repo) c.eventReporter.DefaultBranchUpdated(ctx, &repoevents.DefaultBranchUpdatedPayload{
if err != nil { RepoID: repo.ID,
log.Ctx(ctx).Warn().Err(err).Int64("repo_id", repo.ID). PrincipalID: bootstrap.NewSystemServiceSession().Principal.ID,
Msgf("failed to index repo with the updated default branch %s", in.Name) OldName: oldName,
} NewName: repo.DefaultBranch,
})
return repo, nil return repo, nil
} }

View File

@ -21,6 +21,7 @@ import (
"github.com/harness/gitness/app/services/codeowners" "github.com/harness/gitness/app/services/codeowners"
"github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/importer"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/services/settings"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
@ -58,6 +59,7 @@ func ProvideController(
reporeporter *repoevents.Reporter, reporeporter *repoevents.Reporter,
indexer keywordsearch.Indexer, indexer keywordsearch.Indexer,
limiter limiter.ResourceLimiter, limiter limiter.ResourceLimiter,
locker *locker.Locker,
mtxManager lock.MutexManager, mtxManager lock.MutexManager,
identifierCheck check.RepoIdentifier, identifierCheck check.RepoIdentifier,
repoChecks Check, repoChecks Check,
@ -65,8 +67,8 @@ func ProvideController(
return NewController(config, tx, urlProvider, return NewController(config, tx, urlProvider,
authorizer, repoStore, authorizer, repoStore,
spaceStore, pipelineStore, spaceStore, pipelineStore,
principalStore, ruleStore, settings, principalInfoCache, protectionManager, principalStore, ruleStore, settings, principalInfoCache, protectionManager, rpcClient, importer,
rpcClient, importer, codeOwners, reporeporter, indexer, limiter, mtxManager, identifierCheck, repoChecks) codeOwners, reporeporter, indexer, limiter, locker, mtxManager, identifierCheck, repoChecks)
} }
func ProvideRepoCheck() Check { func ProvideRepoCheck() Check {

View File

@ -88,6 +88,10 @@ var (
http.StatusLocked, http.StatusLocked,
"The requested resource is temporarily locked, please retry the operation.", "The requested resource is temporarily locked, please retry the operation.",
) )
// ErrEmptyRepoNeedsBranch is returned if no branch found on the githook post receieve for empty repositories.
ErrEmptyRepoNeedsBranch = New(http.StatusBadRequest,
"Pushing to an empty repository requires at least one branch with commits.")
) )
// Error represents a json-encoded API error. // Error represents a json-encoded API error.

View File

@ -45,3 +45,27 @@ func (r *Reader) RegisterRepoDeleted(fn events.HandlerFunc[*DeletedPayload],
opts ...events.HandlerOption) error { opts ...events.HandlerOption) error {
return events.ReaderRegisterEvent(r.innerReader, DeletedEvent, fn, opts...) return events.ReaderRegisterEvent(r.innerReader, DeletedEvent, fn, opts...)
} }
const DefaultBranchUpdatedEvent events.EventType = "default-branch-updated"
type DefaultBranchUpdatedPayload struct {
RepoID int64 `json:"repo_id"`
PrincipalID int64 `json:"principal_id"`
OldName string `json:"old_name"`
NewName string `json:"new_name"`
}
func (r *Reporter) DefaultBranchUpdated(ctx context.Context, payload *DefaultBranchUpdatedPayload) {
eventID, err := events.ReporterSendEvent(r.innerReporter, ctx, DefaultBranchUpdatedEvent, payload)
if err != nil {
log.Ctx(ctx).Err(err).Msgf("failed to send default branch updated event")
return
}
log.Ctx(ctx).Debug().Msgf("reported default branch updated event with id '%s'", eventID)
}
func (r *Reader) RegisterDefaultBranchUpdated(fn events.HandlerFunc[*DefaultBranchUpdatedPayload],
opts ...events.HandlerOption) error {
return events.ReaderRegisterEvent(r.innerReader, DefaultBranchUpdatedEvent, fn, opts...)
}

View File

@ -1,83 +0,0 @@
// 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 githook
import (
"github.com/harness/gitness/app/api/controller/githook"
"github.com/harness/gitness/app/api/controller/limiter"
"github.com/harness/gitness/app/auth/authz"
eventsgit "github.com/harness/gitness/app/events/git"
"github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/settings"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/app/url"
"github.com/harness/gitness/git"
"github.com/harness/gitness/git/hook"
"github.com/google/wire"
)
// WireSet provides a wire set for this package.
var WireSet = wire.NewSet(
ProvideController,
ProvideFactory,
)
func ProvideFactory() hook.ClientFactory {
return &ControllerClientFactory{
// will be set in ProvideController (to break cyclic dependency during wiring)
githookCtrl: nil,
}
}
func ProvideController(
authorizer authz.Authorizer,
principalStore store.PrincipalStore,
repoStore store.RepoStore,
gitReporter *eventsgit.Reporter,
git git.Interface,
pullreqStore store.PullReqStore,
urlProvider url.Provider,
protectionManager *protection.Manager,
githookFactory hook.ClientFactory,
limiter limiter.ResourceLimiter,
settings *settings.Service,
preReceiveExtender githook.PreReceiveExtender,
updateExtender githook.UpdateExtender,
postReceiveExtender githook.PostReceiveExtender,
) *githook.Controller {
ctrl := githook.NewController(
authorizer,
principalStore,
repoStore,
gitReporter,
pullreqStore,
urlProvider,
protectionManager,
limiter,
settings,
preReceiveExtender,
updateExtender,
postReceiveExtender,
)
// TODO: improve wiring if possible
if fct, ok := githookFactory.(*ControllerClientFactory); ok {
fct.githookCtrl = ctrl
fct.git = git
}
return ctrl
}

View File

@ -20,6 +20,7 @@ import (
"strings" "strings"
gitevents "github.com/harness/gitness/app/events/git" gitevents "github.com/harness/gitness/app/events/git"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/events" "github.com/harness/gitness/events"
) )
@ -33,6 +34,21 @@ func (s *Service) handleEventBranchUpdated(ctx context.Context,
return s.indexRepo(ctx, event.Payload.RepoID, event.Payload.Ref) return s.indexRepo(ctx, event.Payload.RepoID, event.Payload.Ref)
} }
func (s *Service) handleUpdateDefaultBranch(ctx context.Context,
event *events.Event[*repoevents.DefaultBranchUpdatedPayload]) error {
repo, err := s.repoStore.Find(ctx, event.Payload.RepoID)
if err != nil {
return fmt.Errorf("failed to find repository in db: %w", err)
}
err = s.indexer.Index(ctx, repo)
if err != nil {
return fmt.Errorf("index update failed for repo %d: %w", repo.ID, err)
}
return nil
}
func (s *Service) indexRepo( func (s *Service) indexRepo(
ctx context.Context, ctx context.Context,
repoID int64, repoID int64,
@ -64,6 +80,7 @@ func (s *Service) indexRepo(
func getBranchFromRef(ref string) (string, error) { func getBranchFromRef(ref string) (string, error) {
const refPrefix = "refs/heads/" const refPrefix = "refs/heads/"
if !strings.HasPrefix(ref, refPrefix) { if !strings.HasPrefix(ref, refPrefix) {
return "", fmt.Errorf("failed to get branch name from branch ref %s", ref) return "", fmt.Errorf("failed to get branch name from branch ref %s", ref)
} }

View File

@ -21,14 +21,13 @@ import (
"time" "time"
gitevents "github.com/harness/gitness/app/events/git" gitevents "github.com/harness/gitness/app/events/git"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/events" "github.com/harness/gitness/events"
"github.com/harness/gitness/stream" "github.com/harness/gitness/stream"
) )
const ( const groupGitEvents = "gitness:keywordsearch"
eventsReaderGroupName = "gitness:keywordsearch"
)
type Config struct { type Config struct {
EventReaderName string EventReaderName string
@ -63,6 +62,7 @@ func NewService(
ctx context.Context, ctx context.Context,
config Config, config Config,
gitReaderFactory *events.ReaderFactory[*gitevents.Reader], gitReaderFactory *events.ReaderFactory[*gitevents.Reader],
repoReaderFactory *events.ReaderFactory[*repoevents.Reader],
repoStore store.RepoStore, repoStore store.RepoStore,
indexer Indexer, indexer Indexer,
) (*Service, error) { ) (*Service, error) {
@ -75,7 +75,7 @@ func NewService(
indexer: indexer, indexer: indexer,
} }
_, err := gitReaderFactory.Launch(ctx, eventsReaderGroupName, config.EventReaderName, _, err := gitReaderFactory.Launch(ctx, groupGitEvents, config.EventReaderName,
func(r *gitevents.Reader) error { func(r *gitevents.Reader) error {
const idleTimeout = 1 * time.Minute const idleTimeout = 1 * time.Minute
r.Configure( r.Configure(
@ -95,5 +95,22 @@ func NewService(
return nil, fmt.Errorf("failed to launch git event reader for webhooks: %w", err) return nil, fmt.Errorf("failed to launch git event reader for webhooks: %w", err)
} }
_, err = repoReaderFactory.Launch(ctx, groupGitEvents, config.EventReaderName,
func(r *repoevents.Reader) error {
const idleTimeout = 1 * time.Minute
r.Configure(
stream.WithConcurrency(config.Concurrency),
stream.WithHandlerOptions(
stream.WithIdleTimeout(idleTimeout),
stream.WithMaxRetries(config.MaxRetries),
))
_ = r.RegisterDefaultBranchUpdated((service.handleUpdateDefaultBranch))
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to launch reader factory for repo git group: %w", err)
}
return service, nil return service, nil
} }

View File

@ -18,6 +18,7 @@ import (
"context" "context"
gitevents "github.com/harness/gitness/app/events/git" gitevents "github.com/harness/gitness/app/events/git"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/events" "github.com/harness/gitness/events"
@ -35,12 +36,14 @@ var WireSet = wire.NewSet(
func ProvideService(ctx context.Context, func ProvideService(ctx context.Context,
config Config, config Config,
gitReaderFactory *events.ReaderFactory[*gitevents.Reader], gitReaderFactory *events.ReaderFactory[*gitevents.Reader],
repoReaderFactory *events.ReaderFactory[*repoevents.Reader],
repoStore store.RepoStore, repoStore store.RepoStore,
indexer Indexer, indexer Indexer,
) (*Service, error) { ) (*Service, error) {
return NewService(ctx, return NewService(ctx,
config, config,
gitReaderFactory, gitReaderFactory,
repoReaderFactory,
repoStore, repoStore,
indexer) indexer)
} }

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package repo package locker
import ( import (
"context" "context"
@ -27,38 +27,50 @@ import (
"github.com/rs/zerolog/log" "github.com/rs/zerolog/log"
) )
func (c *Controller) lockDefaultBranch( const namespaceRepo = "repo"
type Locker struct {
mtxManager lock.MutexManager
}
func NewLocker(mtxManager lock.MutexManager) *Locker {
return &Locker{
mtxManager: mtxManager,
}
}
func (l Locker) lock(
ctx context.Context, ctx context.Context,
repoUID string, namespace string,
branchName string, key string,
expiry time.Duration, expiry time.Duration,
) (func(), error) { ) (func(), error) {
key := repoUID + "/defaultBranch"
// annotate logs for easier debugging of lock related issues // annotate logs for easier debugging of lock related issues
// TODO: refactor once common logging annotations are added
ctx = logging.NewContext(ctx, func(zc zerolog.Context) zerolog.Context { ctx = logging.NewContext(ctx, func(zc zerolog.Context) zerolog.Context {
return zc. return zc.
Str("default_branch_lock", key). Str("key", key).
Str("repo_uid", repoUID) Str("namespace", namespaceRepo).
Str("expiry", expiry.String())
}) })
mutext, err := c.mtxManager.NewMutex( mutext, err := l.mtxManager.NewMutex(
key, key,
lock.WithNamespace("repo"), lock.WithNamespace(namespace),
lock.WithExpiry(expiry), lock.WithExpiry(expiry),
lock.WithTimeoutFactor(4/expiry.Seconds()), // 4s lock.WithTimeoutFactor(4/expiry.Seconds()), // 4s
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to create new mutex for repo %q with default branch %s: %w", repoUID, branchName, err) return nil, fmt.Errorf("failed to create new mutex: %w", err)
} }
log.Ctx(ctx).Debug().Msg("attempting to acquire lock")
err = mutext.Lock(ctx) err = mutext.Lock(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to lock the mutex for repo %q with default branch %s: %w", repoUID, branchName, err) return nil, fmt.Errorf("failed to lock the mutex: %w", err)
} }
log.Ctx(ctx).Info().Msgf("successfully locked the repo default branch (expiry: %s)", expiry) log.Ctx(ctx).Debug().Msgf("successfully locked (expiry: %s)", expiry)
unlockFn := func() { unlockFn := func() {
// always unlock independent of whether source context got canceled or not // always unlock independent of whether source context got canceled or not
@ -70,10 +82,11 @@ func (c *Controller) lockDefaultBranch(
err := mutext.Unlock(ctx) err := mutext.Unlock(ctx)
if err != nil { if err != nil {
log.Ctx(ctx).Warn().Err(err).Msg("failed to unlock repo default branch") log.Ctx(ctx).Warn().Err(err).Msg("failed to unlock")
} else { } else {
log.Ctx(ctx).Info().Msg("successfully unlocked repo default branch") log.Ctx(ctx).Debug().Msg("successfully unlocked")
} }
} }
return unlockFn, nil return unlockFn, nil
} }

View File

@ -0,0 +1,41 @@
// 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 locker
import (
"context"
"fmt"
"strconv"
"time"
)
func (l Locker) LockPR(
ctx context.Context,
repoID int64,
prNum int64,
expiry time.Duration,
) (func(), error) {
key := fmt.Sprintf("%d/pulls", repoID)
if prNum != 0 {
key += "/" + strconv.FormatInt(prNum, 10)
}
unlockFn, err := l.lock(ctx, namespaceRepo, key, expiry)
if err != nil {
return nil, fmt.Errorf("failed to lock mutex for pr %d in repo %d: %w", prNum, repoID, err)
}
return unlockFn, nil
}

View File

@ -0,0 +1,42 @@
// 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 locker
import (
"context"
"fmt"
"strconv"
"time"
"github.com/rs/zerolog/log"
)
func (l Locker) LockDefaultBranch(
ctx context.Context,
repoID int64,
branchName string,
expiry time.Duration,
) (func(), error) {
key := strconv.FormatInt(repoID, 10) + "/defaultBranch"
log.Ctx(ctx).Info().Msg("attempting to lock to update the repo default branch")
unlockFn, err := l.lock(ctx, namespaceRepo, key, expiry)
if err != nil {
return nil, fmt.Errorf("failed to lock repo to update default branch to %s: %w", branchName, err)
}
return unlockFn, nil
}

View File

@ -0,0 +1,29 @@
// 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 locker
import (
"github.com/harness/gitness/lock"
"github.com/google/wire"
)
var WireSet = wire.NewSet(
ProvideLocker,
)
func ProvideLocker(mtxManager lock.MutexManager) *Locker {
return NewLocker(mtxManager)
}

View File

@ -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 repo
import (
"context"
"fmt"
"time"
"github.com/harness/gitness/app/bootstrap"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/githook"
"github.com/harness/gitness/events"
"github.com/harness/gitness/git"
"github.com/rs/zerolog/log"
)
// handleUpdateDefaultBranch handles git update default branch using branch name from db (not event payload).
func (s *Service) handleUpdateDefaultBranch(
ctx context.Context,
event *events.Event[*repoevents.DefaultBranchUpdatedPayload],
) error {
// the max time we give an update default branch to succeed
const timeout = 2 * time.Minute
unlock, err := s.locker.LockDefaultBranch(
ctx,
event.Payload.RepoID,
event.Payload.NewName, // only used for logging
timeout+30*time.Second, // add 30s to the lock to give enough time for updating default branch
)
if err != nil {
return fmt.Errorf("failed to lock repo for updating default branch to %s", event.Payload.NewName)
}
defer unlock()
repo, err := s.repoStore.Find(ctx, event.Payload.RepoID)
if err != nil {
return fmt.Errorf("update default branch handler failed to find the repo: %w", err)
}
// create new, time-restricted context to guarantee update completion, even if request is canceled.
// TODO: a proper error handling solution required.
ctx, cancel := context.WithTimeout(
ctx,
timeout,
)
defer cancel()
systemPrincipal := bootstrap.NewSystemServiceSession().Principal
envVars, err := githook.GenerateEnvironmentVariables(
ctx,
s.urlProvider.GetInternalAPIURL(),
repo.ID,
systemPrincipal.ID,
true,
true,
)
if err != nil {
return fmt.Errorf("failed to generate git hook env variables: %w", err)
}
err = s.git.UpdateDefaultBranch(ctx, &git.UpdateDefaultBranchParams{
WriteParams: git.WriteParams{
Actor: git.Identity{
Name: systemPrincipal.DisplayName,
Email: systemPrincipal.Email,
},
RepoUID: repo.GitUID,
EnvVars: envVars,
},
BranchName: repo.DefaultBranch,
})
if err != nil {
return fmt.Errorf("failed to update the repo default branch to %s", repo.DefaultBranch)
}
log.Ctx(ctx).Info().Msgf("git repo default branch updated to %s by default branch event handler", repo.DefaultBranch)
return nil
}

View File

@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package reposize package repo
import ( import (
"context" "context"
@ -30,7 +30,7 @@ import (
const jobType = "repo-size-calculator" const jobType = "repo-size-calculator"
type Calculator struct { type SizeCalculator struct {
enabled bool enabled bool
cron string cron string
maxDur time.Duration maxDur time.Duration
@ -40,12 +40,12 @@ type Calculator struct {
scheduler *job.Scheduler scheduler *job.Scheduler
} }
func (c *Calculator) Register(ctx context.Context) error { func (s *SizeCalculator) Register(ctx context.Context) error {
if !c.enabled { if !s.enabled {
return nil return nil
} }
err := c.scheduler.AddRecurring(ctx, jobType, jobType, c.cron, c.maxDur) err := s.scheduler.AddRecurring(ctx, jobType, jobType, s.cron, s.maxDur)
if err != nil { if err != nil {
return fmt.Errorf("failed to register recurring job for calculator: %w", err) return fmt.Errorf("failed to register recurring job for calculator: %w", err)
} }
@ -53,17 +53,17 @@ func (c *Calculator) Register(ctx context.Context) error {
return nil return nil
} }
func (c *Calculator) Handle(ctx context.Context, _ string, _ job.ProgressReporter) (string, error) { func (s *SizeCalculator) Handle(ctx context.Context, _ string, _ job.ProgressReporter) (string, error) {
if !c.enabled { if !s.enabled {
return "", nil return "", nil
} }
sizeInfos, err := c.repoStore.ListSizeInfos(ctx) sizeInfos, err := s.repoStore.ListSizeInfos(ctx)
if err != nil { if err != nil {
return "", fmt.Errorf("failed to get repository sizes: %w", err) return "", fmt.Errorf("failed to get repository sizes: %w", err)
} }
expiredBefore := time.Now().Add(c.maxDur) expiredBefore := time.Now().Add(s.maxDur)
log.Ctx(ctx).Info().Msgf( log.Ctx(ctx).Info().Msgf(
"start repo size calculation (operation timeout: %s)", "start repo size calculation (operation timeout: %s)",
expiredBefore.Format(time.RFC3339Nano), expiredBefore.Format(time.RFC3339Nano),
@ -71,9 +71,9 @@ func (c *Calculator) Handle(ctx context.Context, _ string, _ job.ProgressReporte
var wg sync.WaitGroup var wg sync.WaitGroup
taskCh := make(chan *types.RepositorySizeInfo) taskCh := make(chan *types.RepositorySizeInfo)
for i := 0; i < c.numWorkers; i++ { for i := 0; i < s.numWorkers; i++ {
wg.Add(1) wg.Add(1)
go worker(ctx, c, &wg, taskCh) go worker(ctx, s, &wg, taskCh)
} }
for _, sizeInfo := range sizeInfos { for _, sizeInfo := range sizeInfos {
select { select {
@ -88,7 +88,7 @@ func (c *Calculator) Handle(ctx context.Context, _ string, _ job.ProgressReporte
return "", nil return "", nil
} }
func worker(ctx context.Context, c *Calculator, wg *sync.WaitGroup, taskCh <-chan *types.RepositorySizeInfo) { func worker(ctx context.Context, s *SizeCalculator, wg *sync.WaitGroup, taskCh <-chan *types.RepositorySizeInfo) {
defer wg.Done() defer wg.Done()
for sizeInfo := range taskCh { for sizeInfo := range taskCh {
@ -96,7 +96,7 @@ func worker(ctx context.Context, c *Calculator, wg *sync.WaitGroup, taskCh <-cha
log.Debug().Msgf("previous repo size: %d", sizeInfo.Size) log.Debug().Msgf("previous repo size: %d", sizeInfo.Size)
sizeOut, err := c.git.GetRepositorySize( sizeOut, err := s.git.GetRepositorySize(
ctx, ctx,
&git.GetRepositorySizeParams{ReadParams: git.ReadParams{RepoUID: sizeInfo.GitUID}}) &git.GetRepositorySizeParams{ReadParams: git.ReadParams{RepoUID: sizeInfo.GitUID}})
if err != nil { if err != nil {
@ -108,7 +108,7 @@ func worker(ctx context.Context, c *Calculator, wg *sync.WaitGroup, taskCh <-cha
continue continue
} }
if err := c.repoStore.UpdateSize(ctx, sizeInfo.ID, sizeOut.Size); err != nil { if err := s.repoStore.UpdateSize(ctx, sizeInfo.ID, sizeOut.Size); err != nil {
log.Error().Msgf("failed to update repo size: %s", err.Error()) log.Error().Msgf("failed to update repo size: %s", err.Error())
continue continue
} }

View File

@ -0,0 +1,79 @@
// 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 repo
import (
"context"
"fmt"
"time"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/app/url"
"github.com/harness/gitness/events"
"github.com/harness/gitness/git"
"github.com/harness/gitness/stream"
"github.com/harness/gitness/types"
)
const groupRepo = "gitness:repo"
type Service struct {
repoEvReporter *repoevents.Reporter
repoStore store.RepoStore
urlProvider url.Provider
git git.Interface
locker *locker.Locker
}
func NewService(
ctx context.Context,
config *types.Config,
repoEvReporter *repoevents.Reporter,
repoReaderFactory *events.ReaderFactory[*repoevents.Reader],
repoStore store.RepoStore,
urlProvider url.Provider,
git git.Interface,
locker *locker.Locker,
) (*Service, error) {
service := &Service{
repoEvReporter: repoEvReporter,
repoStore: repoStore,
urlProvider: urlProvider,
git: git,
locker: locker,
}
_, err := repoReaderFactory.Launch(ctx, groupRepo, config.InstanceID,
func(r *repoevents.Reader) error {
const idleTimeout = 15 * time.Second
r.Configure(
stream.WithConcurrency(1),
stream.WithHandlerOptions(
stream.WithIdleTimeout(idleTimeout),
stream.WithMaxRetries(3),
))
_ = r.RegisterDefaultBranchUpdated(service.handleUpdateDefaultBranch)
return nil
})
if err != nil {
return nil, fmt.Errorf("failed to launch reader factory for repo git group: %w", err)
}
return service, nil
}

View File

@ -12,10 +12,16 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
package reposize package repo
import ( import (
"context"
repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/store" "github.com/harness/gitness/app/store"
"github.com/harness/gitness/app/url"
"github.com/harness/gitness/events"
"github.com/harness/gitness/git" "github.com/harness/gitness/git"
"github.com/harness/gitness/job" "github.com/harness/gitness/job"
"github.com/harness/gitness/types" "github.com/harness/gitness/types"
@ -25,6 +31,7 @@ import (
var WireSet = wire.NewSet( var WireSet = wire.NewSet(
ProvideCalculator, ProvideCalculator,
ProvideService,
) )
func ProvideCalculator( func ProvideCalculator(
@ -33,8 +40,8 @@ func ProvideCalculator(
repoStore store.RepoStore, repoStore store.RepoStore,
scheduler *job.Scheduler, scheduler *job.Scheduler,
executor *job.Executor, executor *job.Executor,
) (*Calculator, error) { ) (*SizeCalculator, error) {
job := &Calculator{ job := &SizeCalculator{
enabled: config.RepoSize.Enabled, enabled: config.RepoSize.Enabled,
cron: config.RepoSize.CRON, cron: config.RepoSize.CRON,
maxDur: config.RepoSize.MaxDuration, maxDur: config.RepoSize.MaxDuration,
@ -51,3 +58,16 @@ func ProvideCalculator(
return job, nil return job, nil
} }
func ProvideService(ctx context.Context,
config *types.Config,
repoEvReporter *repoevents.Reporter,
repoReaderFactory *events.ReaderFactory[*repoevents.Reader],
repoStore store.RepoStore,
urlProvider url.Provider,
git git.Interface,
locker *locker.Locker,
) (*Service, error) {
return NewService(ctx, config, repoEvReporter, repoReaderFactory,
repoStore, urlProvider, git, locker)
}

View File

@ -20,7 +20,7 @@ import (
"github.com/harness/gitness/app/services/metric" "github.com/harness/gitness/app/services/metric"
"github.com/harness/gitness/app/services/notification" "github.com/harness/gitness/app/services/notification"
"github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/services/pullreq"
"github.com/harness/gitness/app/services/reposize" "github.com/harness/gitness/app/services/repo"
"github.com/harness/gitness/app/services/trigger" "github.com/harness/gitness/app/services/trigger"
"github.com/harness/gitness/app/services/webhook" "github.com/harness/gitness/app/services/webhook"
"github.com/harness/gitness/job" "github.com/harness/gitness/job"
@ -38,7 +38,8 @@ type Services struct {
Trigger *trigger.Service Trigger *trigger.Service
JobScheduler *job.Scheduler JobScheduler *job.Scheduler
MetricCollector *metric.Collector MetricCollector *metric.Collector
RepoSizeCalculator *reposize.Calculator RepoSizeCalculator *repo.SizeCalculator
Repo *repo.Service
Cleanup *cleanup.Service Cleanup *cleanup.Service
Notification *notification.Service Notification *notification.Service
Keywordsearch *keywordsearch.Service Keywordsearch *keywordsearch.Service
@ -50,7 +51,8 @@ func ProvideServices(
triggerSvc *trigger.Service, triggerSvc *trigger.Service,
jobScheduler *job.Scheduler, jobScheduler *job.Scheduler,
metricCollector *metric.Collector, metricCollector *metric.Collector,
repoSizeCalculator *reposize.Calculator, repoSizeCalculator *repo.SizeCalculator,
repo *repo.Service,
cleanupSvc *cleanup.Service, cleanupSvc *cleanup.Service,
notificationSvc *notification.Service, notificationSvc *notification.Service,
keywordsearchSvc *keywordsearch.Service, keywordsearchSvc *keywordsearch.Service,
@ -62,6 +64,7 @@ func ProvideServices(
JobScheduler: jobScheduler, JobScheduler: jobScheduler,
MetricCollector: metricCollector, MetricCollector: metricCollector,
RepoSizeCalculator: repoSizeCalculator, RepoSizeCalculator: repoSizeCalculator,
Repo: repo,
Cleanup: cleanupSvc, Cleanup: cleanupSvc,
Notification: notificationSvc, Notification: notificationSvc,
Keywordsearch: keywordsearchSvc, Keywordsearch: keywordsearchSvc,

View File

@ -0,0 +1 @@
ALTER TABLE repositories DROP COLUMN repo_is_empty;

View File

@ -0,0 +1 @@
ALTER TABLE repositories ADD COLUMN repo_is_empty BOOLEAN NOT NULL DEFAULT false;

View File

@ -0,0 +1 @@
ALTER TABLE repositories DROP COLUMN repo_is_empty;

View File

@ -0,0 +1 @@
ALTER TABLE repositories ADD COLUMN repo_is_empty BOOLEAN NOT NULL DEFAULT false;

View File

@ -88,6 +88,7 @@ type repository struct {
NumMergedPulls int `db:"repo_num_merged_pulls"` NumMergedPulls int `db:"repo_num_merged_pulls"`
Importing bool `db:"repo_importing"` Importing bool `db:"repo_importing"`
IsEmpty bool `db:"repo_is_empty"`
} }
const ( const (
@ -113,7 +114,8 @@ const (
,repo_num_closed_pulls ,repo_num_closed_pulls
,repo_num_open_pulls ,repo_num_open_pulls
,repo_num_merged_pulls ,repo_num_merged_pulls
,repo_importing` ,repo_importing
,repo_is_empty`
) )
// Find finds the repo by id. // Find finds the repo by id.
@ -238,6 +240,7 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error {
,repo_num_open_pulls ,repo_num_open_pulls
,repo_num_merged_pulls ,repo_num_merged_pulls
,repo_importing ,repo_importing
,repo_is_empty
) values ( ) values (
:repo_version :repo_version
,:repo_parent_id ,:repo_parent_id
@ -260,6 +263,7 @@ func (s *RepoStore) Create(ctx context.Context, repo *types.Repository) error {
,:repo_num_open_pulls ,:repo_num_open_pulls
,:repo_num_merged_pulls ,:repo_num_merged_pulls
,:repo_importing ,:repo_importing
,:repo_is_empty
) RETURNING repo_id` ) RETURNING repo_id`
db := dbtx.GetAccessor(ctx, s.db) db := dbtx.GetAccessor(ctx, s.db)
@ -303,6 +307,7 @@ func (s *RepoStore) Update(ctx context.Context, repo *types.Repository) error {
,repo_num_open_pulls = :repo_num_open_pulls ,repo_num_open_pulls = :repo_num_open_pulls
,repo_num_merged_pulls = :repo_num_merged_pulls ,repo_num_merged_pulls = :repo_num_merged_pulls
,repo_importing = :repo_importing ,repo_importing = :repo_importing
,repo_is_empty = :repo_is_empty
WHERE repo_id = :repo_id AND repo_version = :repo_version - 1` WHERE repo_id = :repo_id AND repo_version = :repo_version - 1`
dbRepo := mapToInternalRepo(repo) dbRepo := mapToInternalRepo(repo)
@ -746,6 +751,7 @@ func (s *RepoStore) mapToRepo(
NumOpenPulls: in.NumOpenPulls, NumOpenPulls: in.NumOpenPulls,
NumMergedPulls: in.NumMergedPulls, NumMergedPulls: in.NumMergedPulls,
Importing: in.Importing, Importing: in.Importing,
IsEmpty: in.IsEmpty,
// Path: is set below // Path: is set below
} }
@ -829,6 +835,7 @@ func mapToInternalRepo(in *types.Repository) *repository {
NumOpenPulls: in.NumOpenPulls, NumOpenPulls: in.NumOpenPulls,
NumMergedPulls: in.NumMergedPulls, NumMergedPulls: in.NumMergedPulls,
Importing: in.Importing, Importing: in.Importing,
IsEmpty: in.IsEmpty,
} }
} }

View File

@ -13,7 +13,7 @@ import (
checkcontroller "github.com/harness/gitness/app/api/controller/check" checkcontroller "github.com/harness/gitness/app/api/controller/check"
"github.com/harness/gitness/app/api/controller/connector" "github.com/harness/gitness/app/api/controller/connector"
"github.com/harness/gitness/app/api/controller/execution" "github.com/harness/gitness/app/api/controller/execution"
ctrlgithook "github.com/harness/gitness/app/api/controller/githook" githookCtrl "github.com/harness/gitness/app/api/controller/githook"
controllerkeywordsearch "github.com/harness/gitness/app/api/controller/keywordsearch" controllerkeywordsearch "github.com/harness/gitness/app/api/controller/keywordsearch"
"github.com/harness/gitness/app/api/controller/limiter" "github.com/harness/gitness/app/api/controller/limiter"
controllerlogs "github.com/harness/gitness/app/api/controller/logs" controllerlogs "github.com/harness/gitness/app/api/controller/logs"
@ -40,7 +40,6 @@ import (
gitevents "github.com/harness/gitness/app/events/git" gitevents "github.com/harness/gitness/app/events/git"
pullreqevents "github.com/harness/gitness/app/events/pullreq" pullreqevents "github.com/harness/gitness/app/events/pullreq"
repoevents "github.com/harness/gitness/app/events/repo" repoevents "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/githook"
"github.com/harness/gitness/app/pipeline/canceler" "github.com/harness/gitness/app/pipeline/canceler"
"github.com/harness/gitness/app/pipeline/commit" "github.com/harness/gitness/app/pipeline/commit"
"github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/converter"
@ -59,12 +58,13 @@ import (
"github.com/harness/gitness/app/services/exporter" "github.com/harness/gitness/app/services/exporter"
"github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/importer"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
locker "github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/metric" "github.com/harness/gitness/app/services/metric"
"github.com/harness/gitness/app/services/notification" "github.com/harness/gitness/app/services/notification"
"github.com/harness/gitness/app/services/notification/mailer" "github.com/harness/gitness/app/services/notification/mailer"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
pullreqservice "github.com/harness/gitness/app/services/pullreq" pullreqservice "github.com/harness/gitness/app/services/pullreq"
"github.com/harness/gitness/app/services/reposize" reposervice "github.com/harness/gitness/app/services/repo"
"github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/services/settings"
"github.com/harness/gitness/app/services/trigger" "github.com/harness/gitness/app/services/trigger"
"github.com/harness/gitness/app/services/usergroup" "github.com/harness/gitness/app/services/usergroup"
@ -142,10 +142,11 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
webhook.WireSet, webhook.WireSet,
cliserver.ProvideTriggerConfig, cliserver.ProvideTriggerConfig,
trigger.WireSet, trigger.WireSet,
githook.WireSet, githookCtrl.ExtenderWireSet,
ctrlgithook.WireSet, githookCtrl.WireSet,
cliserver.ProvideLockConfig, cliserver.ProvideLockConfig,
lock.WireSet, lock.WireSet,
locker.WireSet,
cliserver.ProvidePubsubConfig, cliserver.ProvidePubsubConfig,
pubsub.WireSet, pubsub.WireSet,
cliserver.ProvideJobsConfig, cliserver.ProvideJobsConfig,
@ -178,7 +179,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
canceler.WireSet, canceler.WireSet,
exporter.WireSet, exporter.WireSet,
metric.WireSet, metric.WireSet,
reposize.WireSet, reposervice.WireSet,
cliserver.ProvideCodeOwnerConfig, cliserver.ProvideCodeOwnerConfig,
codeowners.WireSet, codeowners.WireSet,
cliserver.ProvideKeywordSearchConfig, cliserver.ProvideKeywordSearchConfig,

View File

@ -12,7 +12,7 @@ import (
check2 "github.com/harness/gitness/app/api/controller/check" check2 "github.com/harness/gitness/app/api/controller/check"
"github.com/harness/gitness/app/api/controller/connector" "github.com/harness/gitness/app/api/controller/connector"
"github.com/harness/gitness/app/api/controller/execution" "github.com/harness/gitness/app/api/controller/execution"
githook2 "github.com/harness/gitness/app/api/controller/githook" "github.com/harness/gitness/app/api/controller/githook"
keywordsearch2 "github.com/harness/gitness/app/api/controller/keywordsearch" keywordsearch2 "github.com/harness/gitness/app/api/controller/keywordsearch"
"github.com/harness/gitness/app/api/controller/limiter" "github.com/harness/gitness/app/api/controller/limiter"
logs2 "github.com/harness/gitness/app/api/controller/logs" logs2 "github.com/harness/gitness/app/api/controller/logs"
@ -39,7 +39,6 @@ import (
events4 "github.com/harness/gitness/app/events/git" events4 "github.com/harness/gitness/app/events/git"
events3 "github.com/harness/gitness/app/events/pullreq" events3 "github.com/harness/gitness/app/events/pullreq"
events2 "github.com/harness/gitness/app/events/repo" events2 "github.com/harness/gitness/app/events/repo"
"github.com/harness/gitness/app/githook"
"github.com/harness/gitness/app/pipeline/canceler" "github.com/harness/gitness/app/pipeline/canceler"
"github.com/harness/gitness/app/pipeline/commit" "github.com/harness/gitness/app/pipeline/commit"
"github.com/harness/gitness/app/pipeline/converter" "github.com/harness/gitness/app/pipeline/converter"
@ -58,12 +57,13 @@ import (
"github.com/harness/gitness/app/services/exporter" "github.com/harness/gitness/app/services/exporter"
"github.com/harness/gitness/app/services/importer" "github.com/harness/gitness/app/services/importer"
"github.com/harness/gitness/app/services/keywordsearch" "github.com/harness/gitness/app/services/keywordsearch"
"github.com/harness/gitness/app/services/locker"
"github.com/harness/gitness/app/services/metric" "github.com/harness/gitness/app/services/metric"
"github.com/harness/gitness/app/services/notification" "github.com/harness/gitness/app/services/notification"
"github.com/harness/gitness/app/services/notification/mailer" "github.com/harness/gitness/app/services/notification/mailer"
"github.com/harness/gitness/app/services/protection" "github.com/harness/gitness/app/services/protection"
"github.com/harness/gitness/app/services/pullreq" "github.com/harness/gitness/app/services/pullreq"
"github.com/harness/gitness/app/services/reposize" repo2 "github.com/harness/gitness/app/services/repo"
"github.com/harness/gitness/app/services/settings" "github.com/harness/gitness/app/services/settings"
trigger2 "github.com/harness/gitness/app/services/trigger" trigger2 "github.com/harness/gitness/app/services/trigger"
"github.com/harness/gitness/app/services/usergroup" "github.com/harness/gitness/app/services/usergroup"
@ -192,9 +192,10 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
lockerLocker := locker.ProvideLocker(mutexManager)
repoIdentifier := check.ProvideRepoIdentifierCheck() repoIdentifier := check.ProvideRepoIdentifierCheck()
repoCheck := repo.ProvideRepoCheck() repoCheck := repo.ProvideRepoCheck()
repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, mutexManager, repoIdentifier, repoCheck) repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, mutexManager, repoIdentifier, repoCheck)
reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService) reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService)
executionStore := database.ProvideExecutionStore(db) executionStore := database.ProvideExecutionStore(db)
checkStore := database.ProvideCheckStore(db, principalInfoCache) checkStore := database.ProvideCheckStore(db, principalInfoCache)
@ -254,7 +255,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, mutexManager, migrator, pullreqService, protectionManager, streamer, codeownersService) pullreqController := pullreq2.ProvideController(transactor, provider, authorizer, pullReqStore, pullReqActivityStore, codeCommentView, pullReqReviewStore, pullReqReviewerStore, repoStore, principalStore, pullReqFileViewStore, membershipStore, checkStore, gitInterface, eventsReporter, migrator, pullreqService, protectionManager, streamer, codeownersService, lockerLocker)
webhookConfig := server.ProvideWebhookConfig(config) webhookConfig := server.ProvideWebhookConfig(config)
webhookStore := database.ProvideWebhookStore(db) webhookStore := database.ProvideWebhookStore(db)
webhookExecutionStore := database.ProvideWebhookExecutionStore(db) webhookExecutionStore := database.ProvideWebhookExecutionStore(db)
@ -267,19 +268,19 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
preReceiveExtender, err := githook2.ProvidePreReceiveExtender() preReceiveExtender, err := githook.ProvidePreReceiveExtender()
if err != nil { if err != nil {
return nil, err return nil, err
} }
updateExtender, err := githook2.ProvideUpdateExtender() updateExtender, err := githook.ProvideUpdateExtender()
if err != nil { if err != nil {
return nil, err return nil, err
} }
postReceiveExtender, err := githook2.ProvidePostReceiveExtender() postReceiveExtender, err := githook.ProvidePostReceiveExtender()
if err != nil { if err != nil {
return nil, err return nil, err
} }
githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender) githookController := githook.ProvideController(authorizer, principalStore, repoStore, reporter2, reporter, gitInterface, pullReqStore, provider, protectionManager, clientFactory, resourceLimiter, settingsService, preReceiveExtender, updateExtender, postReceiveExtender)
serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore) serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore)
principalController := principal.ProvideController(principalStore) principalController := principal.ProvideController(principalStore)
v := check2.ProvideCheckSanitizers() v := check2.ProvideCheckSanitizers()
@ -319,7 +320,15 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
if err != nil { if err != nil {
return nil, err return nil, err
} }
calculator, err := reposize.ProvideCalculator(config, gitInterface, repoStore, jobScheduler, executor) sizeCalculator, err := repo2.ProvideCalculator(config, gitInterface, repoStore, jobScheduler, executor)
if err != nil {
return nil, err
}
readerFactory2, err := events2.ProvideReaderFactory(eventsSystem)
if err != nil {
return nil, err
}
repoService, err := repo2.ProvideService(ctx, config, reporter, readerFactory2, repoStore, provider, gitInterface, lockerLocker)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -336,11 +345,11 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
return nil, err return nil, err
} }
keywordsearchConfig := server.ProvideKeywordSearchConfig(config) keywordsearchConfig := server.ProvideKeywordSearchConfig(config)
keywordsearchService, err := keywordsearch.ProvideService(ctx, keywordsearchConfig, readerFactory, repoStore, indexer) keywordsearchService, err := keywordsearch.ProvideService(ctx, keywordsearchConfig, readerFactory, readerFactory2, repoStore, indexer)
if err != nil { if err != nil {
return nil, err return nil, err
} }
servicesServices := services.ProvideServices(webhookService, pullreqService, triggerService, jobScheduler, collector, calculator, cleanupService, notificationService, keywordsearchService) servicesServices := services.ProvideServices(webhookService, pullreqService, triggerService, jobScheduler, collector, sizeCalculator, repoService, cleanupService, notificationService, keywordsearchService)
serverSystem := server.NewSystem(bootstrapBootstrap, serverServer, poller, resolverManager, servicesServices) serverSystem := server.NewSystem(bootstrapBootstrap, serverServer, poller, resolverManager, servicesServices)
return serverSystem, nil return serverSystem, nil
} }

View File

@ -50,6 +50,7 @@ type Repository struct {
NumMergedPulls int `json:"num_merged_pulls"` NumMergedPulls int `json:"num_merged_pulls"`
Importing bool `json:"importing"` Importing bool `json:"importing"`
IsEmpty bool `json:"is_empty,omitempty"`
// git urls // git urls
GitURL string `json:"git_url"` GitURL string `json:"git_url"`