mirror of
https://github.com/harness/drone.git
synced 2025-05-05 23:42:57 +00:00
feat: [PIPE-22290]: add additional info to list branches API (#2831)
* change type of branch.SHA from string to sha.SHA * remove code duplication, changed DB query for PRs * add additional info to list branches API
This commit is contained in:
parent
3668c43a2a
commit
5eb79b3805
@ -107,14 +107,14 @@ func (c *Controller) DeleteBranch(ctx context.Context,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return types.DeleteBranchOutput{}, nil, err
|
return types.DeleteBranchOutput{}, nil, err
|
||||||
}
|
}
|
||||||
if pr.SourceSHA != branch.SHA {
|
if pr.SourceSHA != branch.SHA.String() {
|
||||||
return types.DeleteBranchOutput{}, nil, errors.Conflict("source branch SHA does not match pull request source SHA")
|
return types.DeleteBranchOutput{}, nil, errors.Conflict("source branch SHA does not match pull request source SHA")
|
||||||
}
|
}
|
||||||
|
|
||||||
err = c.git.DeleteBranch(ctx, &git.DeleteBranchParams{
|
err = c.git.DeleteBranch(ctx, &git.DeleteBranchParams{
|
||||||
WriteParams: writeParams,
|
WriteParams: writeParams,
|
||||||
BranchName: branchName,
|
BranchName: branchName,
|
||||||
SHA: branch.SHA,
|
SHA: branch.SHA.String(),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.DeleteBranchOutput{}, nil, err
|
return types.DeleteBranchOutput{}, nil, err
|
||||||
@ -126,7 +126,7 @@ func (c *Controller) DeleteBranch(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, err := c.activityStore.CreateWithPayload(ctx, pr, session.Principal.ID,
|
_, err := c.activityStore.CreateWithPayload(ctx, pr, session.Principal.ID,
|
||||||
&types.PullRequestActivityPayloadBranchDelete{SHA: branch.SHA}, nil)
|
&types.PullRequestActivityPayloadBranchDelete{SHA: branch.SHA.String()}, nil)
|
||||||
return err
|
return err
|
||||||
}()
|
}()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -81,6 +81,8 @@ type Controller struct {
|
|||||||
executionStore store.ExecutionStore
|
executionStore store.ExecutionStore
|
||||||
principalStore store.PrincipalStore
|
principalStore store.PrincipalStore
|
||||||
ruleStore store.RuleStore
|
ruleStore store.RuleStore
|
||||||
|
checkStore store.CheckStore
|
||||||
|
pullReqStore store.PullReqStore
|
||||||
settings *settings.Service
|
settings *settings.Service
|
||||||
principalInfoCache store.PrincipalInfoCache
|
principalInfoCache store.PrincipalInfoCache
|
||||||
userGroupStore store.UserGroupStore
|
userGroupStore store.UserGroupStore
|
||||||
@ -113,6 +115,8 @@ func NewController(
|
|||||||
executionStore store.ExecutionStore,
|
executionStore store.ExecutionStore,
|
||||||
principalStore store.PrincipalStore,
|
principalStore store.PrincipalStore,
|
||||||
ruleStore store.RuleStore,
|
ruleStore store.RuleStore,
|
||||||
|
checkStore store.CheckStore,
|
||||||
|
pullReqStore store.PullReqStore,
|
||||||
settings *settings.Service,
|
settings *settings.Service,
|
||||||
principalInfoCache store.PrincipalInfoCache,
|
principalInfoCache store.PrincipalInfoCache,
|
||||||
protectionManager *protection.Manager,
|
protectionManager *protection.Manager,
|
||||||
@ -144,6 +148,8 @@ func NewController(
|
|||||||
executionStore: executionStore,
|
executionStore: executionStore,
|
||||||
principalStore: principalStore,
|
principalStore: principalStore,
|
||||||
ruleStore: ruleStore,
|
ruleStore: ruleStore,
|
||||||
|
checkStore: checkStore,
|
||||||
|
pullReqStore: pullReqStore,
|
||||||
settings: settings,
|
settings: settings,
|
||||||
principalInfoCache: principalInfoCache,
|
principalInfoCache: principalInfoCache,
|
||||||
protectionManager: protectionManager,
|
protectionManager: protectionManager,
|
||||||
|
@ -30,7 +30,8 @@ func (c *Controller) GetBranch(ctx context.Context,
|
|||||||
session *auth.Session,
|
session *auth.Session,
|
||||||
repoRef string,
|
repoRef string,
|
||||||
branchName string,
|
branchName string,
|
||||||
) (*types.Branch, error) {
|
options types.BranchMetadataOptions,
|
||||||
|
) (*types.BranchExtended, error) {
|
||||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -44,10 +45,22 @@ func (c *Controller) GetBranch(ctx context.Context,
|
|||||||
return nil, fmt.Errorf("failed to get branch: %w", err)
|
return nil, fmt.Errorf("failed to get branch: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
metadata, err := c.collectBranchMetadata(ctx, repo, []git.Branch{rpcOut.Branch}, options)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("fail to collect branch metadata: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
branch, err := controller.MapBranch(rpcOut.Branch)
|
branch, err := controller.MapBranch(rpcOut.Branch)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to map branch: %w", err)
|
return nil, fmt.Errorf("failed to map branch: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return &branch, nil
|
branchExtended := &types.BranchExtended{
|
||||||
|
Branch: branch,
|
||||||
|
IsDefault: branchName == repo.DefaultBranch,
|
||||||
|
}
|
||||||
|
|
||||||
|
metadata.apply(0, branchExtended)
|
||||||
|
|
||||||
|
return branchExtended, nil
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/harness/gitness/app/api/usererror"
|
"github.com/harness/gitness/app/api/usererror"
|
||||||
"github.com/harness/gitness/app/auth"
|
"github.com/harness/gitness/app/auth"
|
||||||
"github.com/harness/gitness/git"
|
"github.com/harness/gitness/git"
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -40,20 +41,12 @@ type CommitDivergenceRequest struct {
|
|||||||
To string `json:"to"`
|
To string `json:"to"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitDivergence contains the information of the count of converging commits between two refs.
|
|
||||||
type CommitDivergence struct {
|
|
||||||
// Ahead is the count of commits the 'From' ref is ahead of the 'To' ref.
|
|
||||||
Ahead int32 `json:"ahead"`
|
|
||||||
// Behind is the count of commits the 'From' ref is behind the 'To' ref.
|
|
||||||
Behind int32 `json:"behind"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCommitDivergences returns the commit divergences between reference pairs.
|
// GetCommitDivergences returns the commit divergences between reference pairs.
|
||||||
func (c *Controller) GetCommitDivergences(ctx context.Context,
|
func (c *Controller) GetCommitDivergences(ctx context.Context,
|
||||||
session *auth.Session,
|
session *auth.Session,
|
||||||
repoRef string,
|
repoRef string,
|
||||||
in *GetCommitDivergencesInput,
|
in *GetCommitDivergencesInput,
|
||||||
) ([]CommitDivergence, error) {
|
) ([]types.CommitDivergence, error) {
|
||||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -61,7 +54,7 @@ func (c *Controller) GetCommitDivergences(ctx context.Context,
|
|||||||
|
|
||||||
// if no requests were provided return an empty list
|
// if no requests were provided return an empty list
|
||||||
if in == nil || len(in.Requests) == 0 {
|
if in == nil || len(in.Requests) == 0 {
|
||||||
return []CommitDivergence{}, nil
|
return []types.CommitDivergence{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// if num of requests > page max return error
|
// if num of requests > page max return error
|
||||||
@ -91,10 +84,9 @@ func (c *Controller) GetCommitDivergences(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// map to output type
|
// map to output type
|
||||||
divergences := make([]CommitDivergence, len(rpcOutput.Divergences))
|
divergences := make([]types.CommitDivergence, len(rpcOutput.Divergences))
|
||||||
for i := range rpcOutput.Divergences {
|
for i := range rpcOutput.Divergences {
|
||||||
divergences[i].Ahead = rpcOutput.Divergences[i].Ahead
|
divergences[i] = types.CommitDivergence(rpcOutput.Divergences[i])
|
||||||
divergences[i].Behind = rpcOutput.Divergences[i].Behind
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return divergences, nil
|
return divergences, nil
|
||||||
|
@ -20,18 +20,21 @@ 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/services/protection"
|
||||||
"github.com/harness/gitness/git"
|
"github.com/harness/gitness/git"
|
||||||
|
"github.com/harness/gitness/git/sha"
|
||||||
"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"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ListBranches lists the branches of a repo.
|
// ListBranches lists the branches of a repo.
|
||||||
func (c *Controller) ListBranches(ctx context.Context,
|
func (c *Controller) ListBranches(ctx context.Context,
|
||||||
session *auth.Session,
|
session *auth.Session,
|
||||||
repoRef string,
|
repoRef string,
|
||||||
includeCommit bool,
|
|
||||||
filter *types.BranchFilter,
|
filter *types.BranchFilter,
|
||||||
) ([]types.Branch, error) {
|
) ([]types.BranchExtended, error) {
|
||||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -39,7 +42,7 @@ func (c *Controller) ListBranches(ctx context.Context,
|
|||||||
|
|
||||||
rpcOut, err := c.git.ListBranches(ctx, &git.ListBranchesParams{
|
rpcOut, err := c.git.ListBranches(ctx, &git.ListBranchesParams{
|
||||||
ReadParams: git.CreateReadParams(repo),
|
ReadParams: git.CreateReadParams(repo),
|
||||||
IncludeCommit: includeCommit,
|
IncludeCommit: filter.IncludeCommit,
|
||||||
Query: filter.Query,
|
Query: filter.Query,
|
||||||
Sort: mapToRPCBranchSortOption(filter.Sort),
|
Sort: mapToRPCBranchSortOption(filter.Sort),
|
||||||
Order: mapToRPCSortOrder(filter.Order),
|
Order: mapToRPCSortOrder(filter.Order),
|
||||||
@ -47,18 +50,149 @@ func (c *Controller) ListBranches(ctx context.Context,
|
|||||||
PageSize: int32(filter.Size),
|
PageSize: int32(filter.Size),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("fail to get the list of branches from git: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
branches := make([]types.Branch, len(rpcOut.Branches))
|
branches := rpcOut.Branches
|
||||||
for i := range rpcOut.Branches {
|
|
||||||
branches[i], err = controller.MapBranch(rpcOut.Branches[i])
|
metadata, err := c.collectBranchMetadata(ctx, repo, branches, filter.BranchMetadataOptions)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("fail to collect branch metadata: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
response := make([]types.BranchExtended, len(branches))
|
||||||
|
for i := range branches {
|
||||||
|
response[i].Branch, err = controller.MapBranch(branches[i])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to map branch: %w", err)
|
return nil, fmt.Errorf("failed to map branch: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
response[i].IsDefault = repo.DefaultBranch == branches[i].Name
|
||||||
|
|
||||||
|
metadata.apply(i, &response[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
return branches, nil
|
return response, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// collectBranchMetadata collects the metadata for the provided list of branches.
|
||||||
|
// The metadata includes check, rules, pull requests, and branch divergences.
|
||||||
|
// Each of these would be returned only if the corresponding option is true.
|
||||||
|
func (c *Controller) collectBranchMetadata(
|
||||||
|
ctx context.Context,
|
||||||
|
repo *types.Repository,
|
||||||
|
branches []git.Branch,
|
||||||
|
options types.BranchMetadataOptions,
|
||||||
|
) (branchMetadataOutput, error) {
|
||||||
|
var (
|
||||||
|
checkSummary map[sha.SHA]types.CheckCountSummary
|
||||||
|
branchRuleMap map[string][]types.RuleInfo
|
||||||
|
pullReqMap map[string][]*types.PullReq
|
||||||
|
divergences *git.GetCommitDivergencesOutput
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
|
if options.IncludeChecks {
|
||||||
|
commitSHAs := make([]string, len(branches))
|
||||||
|
for i := range branches {
|
||||||
|
commitSHAs[i] = branches[i].SHA.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
checkSummary, err = c.checkStore.ResultSummary(ctx, repo.ID, commitSHAs)
|
||||||
|
if err != nil {
|
||||||
|
return branchMetadataOutput{}, fmt.Errorf("fail to fetch check summary for commits: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.IncludeRules {
|
||||||
|
rules, err := c.protectionManager.ForRepository(ctx, repo.ID)
|
||||||
|
if err != nil {
|
||||||
|
return branchMetadataOutput{}, fmt.Errorf("failed to fetch protection rules for the repository: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
branchRuleMap = make(map[string][]types.RuleInfo)
|
||||||
|
for i := range branches {
|
||||||
|
branchName := branches[i].Name
|
||||||
|
|
||||||
|
branchRuleInfos, err := protection.GetRuleInfos(
|
||||||
|
rules,
|
||||||
|
repo.DefaultBranch,
|
||||||
|
branchName,
|
||||||
|
protection.RuleInfoFilterStatusActive,
|
||||||
|
protection.RuleInfoFilterTypeBranch)
|
||||||
|
if err != nil {
|
||||||
|
return branchMetadataOutput{}, fmt.Errorf("failed get branch rule infos: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
branchRuleMap[branchName] = branchRuleInfos
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.IncludePullReqs {
|
||||||
|
branchNames := make([]string, len(branches))
|
||||||
|
for i := range branches {
|
||||||
|
branchNames[i] = branches[i].Name
|
||||||
|
}
|
||||||
|
|
||||||
|
pullReqMap, err = c.pullReqStore.ListOpenByBranchName(ctx, repo.ID, branchNames)
|
||||||
|
if err != nil {
|
||||||
|
return branchMetadataOutput{}, fmt.Errorf("fail to fetch pull requests per branch: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if options.MaxDivergence > 0 {
|
||||||
|
readParams := git.CreateReadParams(repo)
|
||||||
|
|
||||||
|
divergenceRequests := make([]git.CommitDivergenceRequest, len(branches))
|
||||||
|
for i := range branches {
|
||||||
|
divergenceRequests[i].From = branches[i].Name
|
||||||
|
divergenceRequests[i].To = repo.DefaultBranch
|
||||||
|
}
|
||||||
|
|
||||||
|
divergences, err = c.git.GetCommitDivergences(ctx, &git.GetCommitDivergencesParams{
|
||||||
|
ReadParams: readParams,
|
||||||
|
MaxCount: int32(options.MaxDivergence),
|
||||||
|
Requests: divergenceRequests,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return branchMetadataOutput{}, fmt.Errorf("fail to fetch commit divergences: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return branchMetadataOutput{
|
||||||
|
checkSummary: checkSummary,
|
||||||
|
branchRuleMap: branchRuleMap,
|
||||||
|
pullReqMap: pullReqMap,
|
||||||
|
divergences: divergences,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type branchMetadataOutput struct {
|
||||||
|
checkSummary map[sha.SHA]types.CheckCountSummary
|
||||||
|
branchRuleMap map[string][]types.RuleInfo
|
||||||
|
pullReqMap map[string][]*types.PullReq
|
||||||
|
divergences *git.GetCommitDivergencesOutput
|
||||||
|
}
|
||||||
|
|
||||||
|
func (metadata branchMetadataOutput) apply(
|
||||||
|
idx int,
|
||||||
|
branch *types.BranchExtended,
|
||||||
|
) {
|
||||||
|
if metadata.checkSummary != nil {
|
||||||
|
branch.CheckSummary = ptr.Of(metadata.checkSummary[branch.SHA])
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.branchRuleMap != nil {
|
||||||
|
branch.Rules = metadata.branchRuleMap[branch.Name]
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.pullReqMap != nil {
|
||||||
|
branch.PullRequests = metadata.pullReqMap[branch.Name]
|
||||||
|
}
|
||||||
|
|
||||||
|
if metadata.divergences != nil {
|
||||||
|
branch.CommitDivergence = ptr.Of(types.CommitDivergence(metadata.divergences.Divergences[idx]))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func mapToRPCBranchSortOption(o enum.BranchSortOption) git.BranchSortOption {
|
func mapToRPCBranchSortOption(o enum.BranchSortOption) git.BranchSortOption {
|
||||||
|
@ -56,6 +56,8 @@ func ProvideController(
|
|||||||
principalStore store.PrincipalStore,
|
principalStore store.PrincipalStore,
|
||||||
executionStore store.ExecutionStore,
|
executionStore store.ExecutionStore,
|
||||||
ruleStore store.RuleStore,
|
ruleStore store.RuleStore,
|
||||||
|
checkStore store.CheckStore,
|
||||||
|
pullReqStore store.PullReqStore,
|
||||||
settings *settings.Service,
|
settings *settings.Service,
|
||||||
principalInfoCache store.PrincipalInfoCache,
|
principalInfoCache store.PrincipalInfoCache,
|
||||||
protectionManager *protection.Manager,
|
protectionManager *protection.Manager,
|
||||||
@ -79,7 +81,8 @@ func ProvideController(
|
|||||||
return NewController(config, tx, urlProvider,
|
return NewController(config, tx, urlProvider,
|
||||||
authorizer,
|
authorizer,
|
||||||
repoStore, spaceStore, pipelineStore, executionStore,
|
repoStore, spaceStore, pipelineStore, executionStore,
|
||||||
principalStore, ruleStore, settings, principalInfoCache, protectionManager, rpcClient, importer,
|
principalStore, ruleStore, checkStore, pullReqStore, settings,
|
||||||
|
principalInfoCache, protectionManager, rpcClient, importer,
|
||||||
codeOwners, reporeporter, indexer, limiter, locker, auditService, mtxManager, identifierCheck,
|
codeOwners, reporeporter, indexer, limiter, locker, auditService, mtxManager, identifierCheck,
|
||||||
repoChecks, publicAccess, labelSvc, instrumentation, userGroupStore, userGroupService)
|
repoChecks, publicAccess, labelSvc, instrumentation, userGroupStore, userGroupService)
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ func MapBranch(b git.Branch) (types.Branch, error) {
|
|||||||
}
|
}
|
||||||
return types.Branch{
|
return types.Branch{
|
||||||
Name: b.Name,
|
Name: b.Name,
|
||||||
SHA: b.SHA.String(),
|
SHA: b.SHA,
|
||||||
Commit: commit,
|
Commit: commit,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -22,9 +22,7 @@ import (
|
|||||||
"github.com/harness/gitness/app/api/request"
|
"github.com/harness/gitness/app/api/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
// HandleGetBranch returns a given branch.
|
||||||
* Gets a given branch.
|
|
||||||
*/
|
|
||||||
func HandleGetBranch(repoCtrl *repo.Controller) http.HandlerFunc {
|
func HandleGetBranch(repoCtrl *repo.Controller) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@ -34,13 +32,20 @@ func HandleGetBranch(repoCtrl *repo.Controller) http.HandlerFunc {
|
|||||||
render.TranslatedUserError(ctx, w, err)
|
render.TranslatedUserError(ctx, w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
branchName, err := request.GetRemainderFromPath(r)
|
branchName, err := request.GetRemainderFromPath(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.TranslatedUserError(ctx, w, err)
|
render.TranslatedUserError(ctx, w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
branch, err := repoCtrl.GetBranch(ctx, session, repoRef, branchName)
|
options, err := request.ParseBranchMetadataOptions(r)
|
||||||
|
if err != nil {
|
||||||
|
render.TranslatedUserError(ctx, w, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
branch, err := repoCtrl.GetBranch(ctx, session, repoRef, branchName, options)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.TranslatedUserError(ctx, w, err)
|
render.TranslatedUserError(ctx, w, err)
|
||||||
return
|
return
|
||||||
|
@ -22,9 +22,7 @@ import (
|
|||||||
"github.com/harness/gitness/app/api/request"
|
"github.com/harness/gitness/app/api/request"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
// HandleListBranches writes json-encoded branch list to the http response body.
|
||||||
* Writes json-encoded branch information to the http response body.
|
|
||||||
*/
|
|
||||||
func HandleListBranches(repoCtrl *repo.Controller) http.HandlerFunc {
|
func HandleListBranches(repoCtrl *repo.Controller) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
ctx := r.Context()
|
ctx := r.Context()
|
||||||
@ -35,15 +33,13 @@ func HandleListBranches(repoCtrl *repo.Controller) http.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
includeCommit, err := request.GetIncludeCommitFromQueryOrDefault(r, false)
|
filter, err := request.ParseBranchFilter(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.TranslatedUserError(ctx, w, err)
|
render.TranslatedUserError(ctx, w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
filter := request.ParseBranchFilter(r)
|
branches, err := repoCtrl.ListBranches(ctx, session, repoRef, filter)
|
||||||
|
|
||||||
branches, err := repoCtrl.ListBranches(ctx, session, repoRef, includeCommit, filter)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
render.TranslatedUserError(ctx, w, err)
|
render.TranslatedUserError(ctx, w, err)
|
||||||
return
|
return
|
||||||
|
@ -312,6 +312,71 @@ var queryParameterIncludeCommit = openapi3.ParameterOrRef{
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var queryParameterIncludeChecks = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamIncludeChecks,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String(
|
||||||
|
"If true, the summary of check for the branch commit SHA would be included in the response."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeBoolean),
|
||||||
|
Default: ptrptr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterIncludeRules = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamIncludeRules,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String(
|
||||||
|
"If true, a list of rules that apply to this branch would be included in the response."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeBoolean),
|
||||||
|
Default: ptrptr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterIncludePullReqs = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamIncludePullReqs,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String(
|
||||||
|
"If true, a list of pull requests from the branch would be included in the response."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeBoolean),
|
||||||
|
Default: ptrptr(false),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterMaxDivergence = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamMaxDivergence,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String(
|
||||||
|
"If greater than zero, branch divergence from the default branch will be included in the response. " +
|
||||||
|
"The divergence would be calculated up the this many commits."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeInteger),
|
||||||
|
Default: ptrptr(0),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
var queryParameterIncludeDirectories = openapi3.ParameterOrRef{
|
var queryParameterIncludeDirectories = openapi3.ParameterOrRef{
|
||||||
Parameter: &openapi3.Parameter{
|
Parameter: &openapi3.Parameter{
|
||||||
Name: request.QueryParamIncludeDirectories,
|
Name: request.QueryParamIncludeDirectories,
|
||||||
@ -888,7 +953,7 @@ func repoOperations(reflector *openapi3.Reflector) {
|
|||||||
opCalulateCommitDivergence.WithTags("repository")
|
opCalulateCommitDivergence.WithTags("repository")
|
||||||
opCalulateCommitDivergence.WithMapOfAnything(map[string]interface{}{"operationId": "calculateCommitDivergence"})
|
opCalulateCommitDivergence.WithMapOfAnything(map[string]interface{}{"operationId": "calculateCommitDivergence"})
|
||||||
_ = reflector.SetRequest(&opCalulateCommitDivergence, new(calculateCommitDivergenceRequest), http.MethodPost)
|
_ = reflector.SetRequest(&opCalulateCommitDivergence, new(calculateCommitDivergenceRequest), http.MethodPost)
|
||||||
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, []repo.CommitDivergence{}, http.StatusOK)
|
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, []types.CommitDivergence{}, http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, new(usererror.Error), http.StatusInternalServerError)
|
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, new(usererror.Error), http.StatusInternalServerError)
|
||||||
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, new(usererror.Error), http.StatusUnauthorized)
|
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, new(usererror.Error), http.StatusUnauthorized)
|
||||||
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, new(usererror.Error), http.StatusForbidden)
|
_ = reflector.SetJSONResponse(&opCalulateCommitDivergence, new(usererror.Error), http.StatusForbidden)
|
||||||
@ -911,8 +976,12 @@ func repoOperations(reflector *openapi3.Reflector) {
|
|||||||
opGetBranch := openapi3.Operation{}
|
opGetBranch := openapi3.Operation{}
|
||||||
opGetBranch.WithTags("repository")
|
opGetBranch.WithTags("repository")
|
||||||
opGetBranch.WithMapOfAnything(map[string]interface{}{"operationId": "getBranch"})
|
opGetBranch.WithMapOfAnything(map[string]interface{}{"operationId": "getBranch"})
|
||||||
|
opGetBranch.WithParameters(
|
||||||
|
queryParameterIncludeChecks, queryParameterIncludeRules, queryParameterIncludePullReqs,
|
||||||
|
queryParameterMaxDivergence,
|
||||||
|
)
|
||||||
_ = reflector.SetRequest(&opGetBranch, new(getBranchRequest), http.MethodGet)
|
_ = reflector.SetRequest(&opGetBranch, new(getBranchRequest), http.MethodGet)
|
||||||
_ = reflector.SetJSONResponse(&opGetBranch, new(types.Branch), http.StatusOK)
|
_ = reflector.SetJSONResponse(&opGetBranch, new(types.BranchExtended), http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&opGetBranch, new(usererror.Error), http.StatusInternalServerError)
|
_ = reflector.SetJSONResponse(&opGetBranch, new(usererror.Error), http.StatusInternalServerError)
|
||||||
_ = reflector.SetJSONResponse(&opGetBranch, new(usererror.Error), http.StatusUnauthorized)
|
_ = reflector.SetJSONResponse(&opGetBranch, new(usererror.Error), http.StatusUnauthorized)
|
||||||
_ = reflector.SetJSONResponse(&opGetBranch, new(usererror.Error), http.StatusForbidden)
|
_ = reflector.SetJSONResponse(&opGetBranch, new(usererror.Error), http.StatusForbidden)
|
||||||
@ -935,11 +1004,15 @@ func repoOperations(reflector *openapi3.Reflector) {
|
|||||||
opListBranches := openapi3.Operation{}
|
opListBranches := openapi3.Operation{}
|
||||||
opListBranches.WithTags("repository")
|
opListBranches.WithTags("repository")
|
||||||
opListBranches.WithMapOfAnything(map[string]interface{}{"operationId": "listBranches"})
|
opListBranches.WithMapOfAnything(map[string]interface{}{"operationId": "listBranches"})
|
||||||
opListBranches.WithParameters(queryParameterIncludeCommit,
|
opListBranches.WithParameters(
|
||||||
queryParameterQueryBranches, queryParameterOrder, queryParameterSortBranch,
|
queryParameterQueryBranches, queryParameterOrder, queryParameterSortBranch,
|
||||||
QueryParameterPage, QueryParameterLimit)
|
QueryParameterPage, QueryParameterLimit,
|
||||||
|
queryParameterIncludeCommit,
|
||||||
|
queryParameterIncludeChecks, queryParameterIncludeRules, queryParameterIncludePullReqs,
|
||||||
|
queryParameterMaxDivergence,
|
||||||
|
)
|
||||||
_ = reflector.SetRequest(&opListBranches, new(listBranchesRequest), http.MethodGet)
|
_ = reflector.SetRequest(&opListBranches, new(listBranchesRequest), http.MethodGet)
|
||||||
_ = reflector.SetJSONResponse(&opListBranches, []types.Branch{}, http.StatusOK)
|
_ = reflector.SetJSONResponse(&opListBranches, []types.BranchExtended{}, http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&opListBranches, new(usererror.Error), http.StatusInternalServerError)
|
_ = reflector.SetJSONResponse(&opListBranches, new(usererror.Error), http.StatusInternalServerError)
|
||||||
_ = reflector.SetJSONResponse(&opListBranches, new(usererror.Error), http.StatusUnauthorized)
|
_ = reflector.SetJSONResponse(&opListBranches, new(usererror.Error), http.StatusUnauthorized)
|
||||||
_ = reflector.SetJSONResponse(&opListBranches, new(usererror.Error), http.StatusForbidden)
|
_ = reflector.SetJSONResponse(&opListBranches, new(usererror.Error), http.StatusForbidden)
|
||||||
|
@ -44,6 +44,11 @@ const (
|
|||||||
QueryParamInternal = "internal"
|
QueryParamInternal = "internal"
|
||||||
QueryParamService = "service"
|
QueryParamService = "service"
|
||||||
QueryParamCommitSHA = "commit_sha"
|
QueryParamCommitSHA = "commit_sha"
|
||||||
|
|
||||||
|
QueryParamIncludeChecks = "include_checks"
|
||||||
|
QueryParamIncludeRules = "include_rules"
|
||||||
|
QueryParamIncludePullReqs = "include_pullreqs"
|
||||||
|
QueryParamMaxDivergence = "max_divergence"
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetGitRefFromQueryOrDefault(r *http.Request, deflt string) string {
|
func GetGitRefFromQueryOrDefault(r *http.Request, deflt string) string {
|
||||||
@ -54,6 +59,22 @@ func GetIncludeCommitFromQueryOrDefault(r *http.Request, deflt bool) (bool, erro
|
|||||||
return QueryParamAsBoolOrDefault(r, QueryParamIncludeCommit, deflt)
|
return QueryParamAsBoolOrDefault(r, QueryParamIncludeCommit, deflt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetIncludeChecksFromQueryOrDefault(r *http.Request, deflt bool) (bool, error) {
|
||||||
|
return QueryParamAsBoolOrDefault(r, QueryParamIncludeChecks, deflt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIncludeRulesFromQueryOrDefault(r *http.Request, deflt bool) (bool, error) {
|
||||||
|
return QueryParamAsBoolOrDefault(r, QueryParamIncludeRules, deflt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIncludePullReqsFromQueryOrDefault(r *http.Request, deflt bool) (bool, error) {
|
||||||
|
return QueryParamAsBoolOrDefault(r, QueryParamIncludePullReqs, deflt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetMaxDivergenceFromQueryOrDefault(r *http.Request, deflt int64) (int64, error) {
|
||||||
|
return QueryParamAsPositiveInt64OrDefault(r, QueryParamMaxDivergence, deflt)
|
||||||
|
}
|
||||||
|
|
||||||
func GetIncludeDirectoriesFromQueryOrDefault(r *http.Request, deflt bool) (bool, error) {
|
func GetIncludeDirectoriesFromQueryOrDefault(r *http.Request, deflt bool) (bool, error) {
|
||||||
return QueryParamAsBoolOrDefault(r, QueryParamIncludeDirectories, deflt)
|
return QueryParamAsBoolOrDefault(r, QueryParamIncludeDirectories, deflt)
|
||||||
}
|
}
|
||||||
@ -69,15 +90,56 @@ func ParseSortBranch(r *http.Request) enum.BranchSortOption {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseBranchFilter extracts the branch filter from the url.
|
func ParseBranchMetadataOptions(r *http.Request) (types.BranchMetadataOptions, error) {
|
||||||
func ParseBranchFilter(r *http.Request) *types.BranchFilter {
|
includeChecks, err := GetIncludeChecksFromQueryOrDefault(r, false)
|
||||||
return &types.BranchFilter{
|
if err != nil {
|
||||||
Query: ParseQuery(r),
|
return types.BranchMetadataOptions{}, err
|
||||||
Sort: ParseSortBranch(r),
|
|
||||||
Order: ParseOrder(r),
|
|
||||||
Page: ParsePage(r),
|
|
||||||
Size: ParseLimit(r),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
includeRules, err := GetIncludeRulesFromQueryOrDefault(r, false)
|
||||||
|
if err != nil {
|
||||||
|
return types.BranchMetadataOptions{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
includePullReqs, err := GetIncludePullReqsFromQueryOrDefault(r, false)
|
||||||
|
if err != nil {
|
||||||
|
return types.BranchMetadataOptions{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
maxDivergence, err := GetMaxDivergenceFromQueryOrDefault(r, 0)
|
||||||
|
if err != nil {
|
||||||
|
return types.BranchMetadataOptions{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return types.BranchMetadataOptions{
|
||||||
|
IncludeChecks: includeChecks,
|
||||||
|
IncludeRules: includeRules,
|
||||||
|
IncludePullReqs: includePullReqs,
|
||||||
|
MaxDivergence: int(maxDivergence),
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ParseBranchFilter extracts the branch filter from the url.
|
||||||
|
func ParseBranchFilter(r *http.Request) (*types.BranchFilter, error) {
|
||||||
|
includeCommit, err := GetIncludeCommitFromQueryOrDefault(r, false)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
metadataOptions, err := ParseBranchMetadataOptions(r)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.BranchFilter{
|
||||||
|
Query: ParseQuery(r),
|
||||||
|
Sort: ParseSortBranch(r),
|
||||||
|
Order: ParseOrder(r),
|
||||||
|
Page: ParsePage(r),
|
||||||
|
Size: ParseLimit(r),
|
||||||
|
IncludeCommit: includeCommit,
|
||||||
|
BranchMetadataOptions: metadataOptions,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParseSortTag extracts the tag sort parameter from the url.
|
// ParseSortTag extracts the tag sort parameter from the url.
|
||||||
|
68
app/services/protection/get_rule_infos.go
Normal file
68
app/services/protection/get_rule_infos.go
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// 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 protection
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/types"
|
||||||
|
"github.com/harness/gitness/types/enum"
|
||||||
|
)
|
||||||
|
|
||||||
|
var RuleInfoFilterTypeBranch = func(r *types.RuleInfoInternal) (bool, error) {
|
||||||
|
return r.Type == TypeBranch, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var RuleInfoFilterStatusActive = func(r *types.RuleInfoInternal) (bool, error) {
|
||||||
|
return r.State == enum.RuleStateActive, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetRuleInfos(
|
||||||
|
protection Protection,
|
||||||
|
defaultBranch string,
|
||||||
|
branchName string,
|
||||||
|
filterFns ...func(*types.RuleInfoInternal) (bool, error),
|
||||||
|
) (ruleInfos []types.RuleInfo, err error) {
|
||||||
|
v, ok := protection.(ruleSet)
|
||||||
|
if !ok {
|
||||||
|
return ruleInfos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err = v.forEachRuleMatchBranch(
|
||||||
|
defaultBranch,
|
||||||
|
branchName,
|
||||||
|
func(r *types.RuleInfoInternal, _ Protection) error {
|
||||||
|
for _, filterFn := range filterFns {
|
||||||
|
allow, err := filterFn(r)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("rule info filter function error: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !allow {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ruleInfos = append(ruleInfos, r.RuleInfo)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to process each rule in ruleSet: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ruleInfos, nil
|
||||||
|
}
|
@ -62,7 +62,7 @@ func (s ruleSet) MergeVerify(
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return out, nil, fmt.Errorf("failed to merge verify: %w", err)
|
return out, nil, fmt.Errorf("failed to process each rule in ruleSet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return out, violations, nil
|
return out, violations, nil
|
||||||
@ -95,7 +95,7 @@ func (s ruleSet) RequiredChecks(
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RequiredChecksOutput{}, err
|
return RequiredChecksOutput{}, fmt.Errorf("failed to process each rule in ruleSet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return RequiredChecksOutput{
|
return RequiredChecksOutput{
|
||||||
@ -122,7 +122,7 @@ func (s ruleSet) RefChangeVerify(ctx context.Context, in RefChangeVerifyInput) (
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to process each rule in ruleSet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return violations, nil
|
return violations, nil
|
||||||
@ -143,7 +143,7 @@ func (s ruleSet) UserIDs() ([]int64, error) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to process each rule in ruleSet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]int64, 0, len(mapIDs))
|
result := make([]int64, 0, len(mapIDs))
|
||||||
@ -169,7 +169,7 @@ func (s ruleSet) UserGroupIDs() ([]int64, error) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, fmt.Errorf("failed to process each rule in ruleSet: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]int64, 0, len(mapIDs))
|
result := make([]int64, 0, len(mapIDs))
|
||||||
|
@ -20,6 +20,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/git/sha"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
@ -405,6 +406,9 @@ type (
|
|||||||
|
|
||||||
// Stream returns streams pull requests from repositories.
|
// Stream returns streams pull requests from repositories.
|
||||||
Stream(ctx context.Context, opts *types.PullReqFilter) (<-chan *types.PullReq, <-chan error)
|
Stream(ctx context.Context, opts *types.PullReqFilter) (<-chan *types.PullReq, <-chan error)
|
||||||
|
|
||||||
|
// ListOpenByBranchName returns open pull requests for each branch.
|
||||||
|
ListOpenByBranchName(ctx context.Context, repoID int64, branchNames []string) (map[string][]*types.PullReq, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
PullReqActivityStore interface {
|
PullReqActivityStore interface {
|
||||||
@ -633,6 +637,13 @@ type (
|
|||||||
|
|
||||||
// ListResults returns a list of status check results for a specific commit in a repo.
|
// ListResults returns a list of status check results for a specific commit in a repo.
|
||||||
ListResults(ctx context.Context, repoID int64, commitSHA string) ([]types.CheckResult, error)
|
ListResults(ctx context.Context, repoID int64, commitSHA string) ([]types.CheckResult, error)
|
||||||
|
|
||||||
|
// ResultSummary returns a list of status check result summaries for the provided list of commits in a repo.
|
||||||
|
ResultSummary(
|
||||||
|
ctx context.Context,
|
||||||
|
repoID int64,
|
||||||
|
commitSHAs []string,
|
||||||
|
) (map[sha.SHA]types.CheckCountSummary, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
GitspaceConfigStore interface {
|
GitspaceConfigStore interface {
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/store"
|
"github.com/harness/gitness/app/store"
|
||||||
|
"github.com/harness/gitness/git/sha"
|
||||||
"github.com/harness/gitness/store/database"
|
"github.com/harness/gitness/store/database"
|
||||||
"github.com/harness/gitness/store/database/dbtx"
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
@ -28,7 +29,6 @@ import (
|
|||||||
|
|
||||||
"github.com/Masterminds/squirrel"
|
"github.com/Masterminds/squirrel"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var _ store.CheckStore = (*CheckStore)(nil)
|
var _ store.CheckStore = (*CheckStore)(nil)
|
||||||
@ -194,7 +194,7 @@ func (s *CheckStore) Count(ctx context.Context,
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "Failed to convert query to sql")
|
return 0, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := dbtx.GetAccessor(ctx, s.db)
|
db := dbtx.GetAccessor(ctx, s.db)
|
||||||
@ -229,7 +229,7 @@ func (s *CheckStore) List(ctx context.Context,
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
return nil, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := make([]*check, 0)
|
dst := make([]*check, 0)
|
||||||
@ -265,7 +265,7 @@ func (s *CheckStore) ListRecent(ctx context.Context,
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Failed to convert list recent status checks query to sql")
|
return nil, fmt.Errorf("failed to convert list recent status checks query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := make([]string, 0)
|
dst := make([]string, 0)
|
||||||
@ -293,7 +293,7 @@ func (s *CheckStore) ListResults(ctx context.Context,
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
return nil, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
result := make([]types.CheckResult, 0)
|
result := make([]types.CheckResult, 0)
|
||||||
@ -307,6 +307,77 @@ func (s *CheckStore) ListResults(ctx context.Context,
|
|||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ResultSummary returns a list of status check result summaries for the provided list of commits in a repo.
|
||||||
|
func (s *CheckStore) ResultSummary(ctx context.Context,
|
||||||
|
repoID int64,
|
||||||
|
commitSHAs []string,
|
||||||
|
) (map[sha.SHA]types.CheckCountSummary, error) {
|
||||||
|
const selectColumns = `
|
||||||
|
check_commit_sha,
|
||||||
|
COUNT(check_status = 'pending') as "count_pending",
|
||||||
|
COUNT(check_status = 'running') as "count_running",
|
||||||
|
COUNT(check_status = 'success') as "count_success",
|
||||||
|
COUNT(check_status = 'failure') as "count_failure",
|
||||||
|
COUNT(check_status = 'error') as "count_error"`
|
||||||
|
|
||||||
|
stmt := database.Builder.
|
||||||
|
Select(selectColumns).
|
||||||
|
From("checks").
|
||||||
|
Where("check_repo_id = ?", repoID).
|
||||||
|
Where(squirrel.Eq{"check_commit_sha": commitSHAs}).
|
||||||
|
GroupBy("check_commit_sha")
|
||||||
|
|
||||||
|
sql, args, err := stmt.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, s.db)
|
||||||
|
|
||||||
|
rows, err := db.QueryxContext(ctx, sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to execute status check summary query")
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
_ = rows.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
result := make(map[sha.SHA]types.CheckCountSummary)
|
||||||
|
|
||||||
|
for rows.Next() {
|
||||||
|
var commitSHAStr string
|
||||||
|
var countPending int
|
||||||
|
var countRunning int
|
||||||
|
var countSuccess int
|
||||||
|
var countFailure int
|
||||||
|
var countError int
|
||||||
|
err := rows.Scan(&commitSHAStr, &countPending, &countRunning, &countSuccess, &countFailure, &countError)
|
||||||
|
if err != nil {
|
||||||
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to scan values of status check summary query")
|
||||||
|
}
|
||||||
|
|
||||||
|
commitSHA, err := sha.New(commitSHAStr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("invalid commit SHA read from DB: %s", commitSHAStr)
|
||||||
|
}
|
||||||
|
|
||||||
|
result[commitSHA] = types.CheckCountSummary{
|
||||||
|
Pending: countPending,
|
||||||
|
Running: countRunning,
|
||||||
|
Success: countSuccess,
|
||||||
|
Failure: countFailure,
|
||||||
|
Error: countError,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := rows.Err(); err != nil {
|
||||||
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to read status chek summary")
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (*CheckStore) applyOpts(stmt squirrel.SelectBuilder, query string) squirrel.SelectBuilder {
|
func (*CheckStore) applyOpts(stmt squirrel.SelectBuilder, query string) squirrel.SelectBuilder {
|
||||||
if query != "" {
|
if query != "" {
|
||||||
stmt = stmt.Where("LOWER(check_uid) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(query)))
|
stmt = stmt.Where("LOWER(check_uid) LIKE ?", fmt.Sprintf("%%%s%%", strings.ToLower(query)))
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/harness/gitness/app/store"
|
"github.com/harness/gitness/app/store"
|
||||||
|
"github.com/harness/gitness/errors"
|
||||||
gitness_store "github.com/harness/gitness/store"
|
gitness_store "github.com/harness/gitness/store"
|
||||||
"github.com/harness/gitness/store/database"
|
"github.com/harness/gitness/store/database"
|
||||||
"github.com/harness/gitness/store/database/dbtx"
|
"github.com/harness/gitness/store/database/dbtx"
|
||||||
@ -30,7 +31,6 @@ import (
|
|||||||
"github.com/Masterminds/squirrel"
|
"github.com/Masterminds/squirrel"
|
||||||
"github.com/guregu/null"
|
"github.com/guregu/null"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jmoiron/sqlx"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -457,7 +457,7 @@ func (s *PullReqStore) Count(ctx context.Context, opts *types.PullReqFilter) (in
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, errors.Wrap(err, "Failed to convert query to sql")
|
return 0, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
db := dbtx.GetAccessor(ctx, s.db)
|
db := dbtx.GetAccessor(ctx, s.db)
|
||||||
@ -486,7 +486,7 @@ func (s *PullReqStore) List(ctx context.Context, opts *types.PullReqFilter) ([]*
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
return nil, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
dst := make([]*pullReq, 0)
|
dst := make([]*pullReq, 0)
|
||||||
@ -520,7 +520,7 @@ func (s *PullReqStore) Stream(ctx context.Context, opts *types.PullReqFilter) (<
|
|||||||
|
|
||||||
sql, args, err := stmt.ToSql()
|
sql, args, err := stmt.ToSql()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
chErr <- errors.Wrap(err, "Failed to convert query to sql")
|
chErr <- fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -553,6 +553,42 @@ func (s *PullReqStore) Stream(ctx context.Context, opts *types.PullReqFilter) (<
|
|||||||
return chPRs, chErr
|
return chPRs, chErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *PullReqStore) ListOpenByBranchName(
|
||||||
|
ctx context.Context,
|
||||||
|
repoID int64,
|
||||||
|
branchNames []string,
|
||||||
|
) (map[string][]*types.PullReq, error) {
|
||||||
|
columns := pullReqColumnsNoDescription
|
||||||
|
stmt := database.Builder.Select(columns)
|
||||||
|
stmt = stmt.From("pullreqs")
|
||||||
|
stmt = stmt.Where("pullreq_source_repo_id = ?", repoID)
|
||||||
|
stmt = stmt.Where("pullreq_state = ?", enum.PullReqStateOpen)
|
||||||
|
stmt = stmt.Where(squirrel.Eq{"pullreq_source_branch": branchNames})
|
||||||
|
stmt = stmt.OrderBy("pullreq_updated desc")
|
||||||
|
|
||||||
|
sql, args, err := stmt.ToSql()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert query to sql: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
db := dbtx.GetAccessor(ctx, s.db)
|
||||||
|
|
||||||
|
dst := make([]*pullReq, 0)
|
||||||
|
|
||||||
|
err = db.SelectContext(ctx, &dst, sql, args...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to fetch list of PRs by branch")
|
||||||
|
}
|
||||||
|
|
||||||
|
prMap := make(map[string][]*types.PullReq)
|
||||||
|
for _, prDB := range dst {
|
||||||
|
pr := s.mapPullReq(ctx, prDB)
|
||||||
|
prMap[prDB.SourceBranch] = append(prMap[prDB.SourceBranch], pr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return prMap, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *PullReqStore) listQuery(opts *types.PullReqFilter) squirrel.SelectBuilder {
|
func (s *PullReqStore) listQuery(opts *types.PullReqFilter) squirrel.SelectBuilder {
|
||||||
var stmt squirrel.SelectBuilder
|
var stmt squirrel.SelectBuilder
|
||||||
|
|
||||||
|
@ -174,6 +174,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
pipelineStore := database.ProvidePipelineStore(db)
|
pipelineStore := database.ProvidePipelineStore(db)
|
||||||
executionStore := database.ProvideExecutionStore(db)
|
executionStore := database.ProvideExecutionStore(db)
|
||||||
ruleStore := database.ProvideRuleStore(db, principalInfoCache)
|
ruleStore := database.ProvideRuleStore(db, principalInfoCache)
|
||||||
|
checkStore := database.ProvideCheckStore(db, principalInfoCache)
|
||||||
|
pullReqStore := database.ProvidePullReqStore(db, principalInfoCache)
|
||||||
settingsStore := database.ProvideSettingsStore(db)
|
settingsStore := database.ProvideSettingsStore(db)
|
||||||
settingsService := settings.ProvideService(settingsStore)
|
settingsService := settings.ProvideService(settingsStore)
|
||||||
protectionManager, err := protection.ProvideManager(ruleStore)
|
protectionManager, err := protection.ProvideManager(ruleStore)
|
||||||
@ -249,9 +251,8 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
instrumentService := instrument.ProvideService()
|
instrumentService := instrument.ProvideService()
|
||||||
userGroupStore := database.ProvideUserGroupStore(db)
|
userGroupStore := database.ProvideUserGroupStore(db)
|
||||||
searchService := usergroup.ProvideSearchService()
|
searchService := usergroup.ProvideSearchService()
|
||||||
repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, executionStore, ruleStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService, labelService, instrumentService, userGroupStore, searchService)
|
repoController := repo.ProvideController(config, transactor, provider, authorizer, repoStore, spaceStore, pipelineStore, principalStore, executionStore, ruleStore, checkStore, pullReqStore, settingsService, principalInfoCache, protectionManager, gitInterface, repository, codeownersService, reporter, indexer, resourceLimiter, lockerLocker, auditService, mutexManager, repoIdentifier, repoCheck, publicaccessService, labelService, instrumentService, userGroupStore, searchService)
|
||||||
reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, auditService)
|
reposettingsController := reposettings.ProvideController(authorizer, repoStore, settingsService, auditService)
|
||||||
checkStore := database.ProvideCheckStore(db, principalInfoCache)
|
|
||||||
stageStore := database.ProvideStageStore(db)
|
stageStore := database.ProvideStageStore(db)
|
||||||
schedulerScheduler, err := scheduler.ProvideScheduler(stageStore, mutexManager)
|
schedulerScheduler, err := scheduler.ProvideScheduler(stageStore, mutexManager)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -274,7 +275,6 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||||||
connectorStore := database.ProvideConnectorStore(db, secretStore)
|
connectorStore := database.ProvideConnectorStore(db, secretStore)
|
||||||
repoGitInfoView := database.ProvideRepoGitInfoView(db)
|
repoGitInfoView := database.ProvideRepoGitInfoView(db)
|
||||||
repoGitInfoCache := cache.ProvideRepoGitInfoCache(repoGitInfoView)
|
repoGitInfoCache := cache.ProvideRepoGitInfoCache(repoGitInfoView)
|
||||||
pullReqStore := database.ProvidePullReqStore(db, principalInfoCache)
|
|
||||||
listService := pullreq.ProvideListService(transactor, gitInterface, authorizer, spaceStore, repoStore, repoGitInfoCache, pullReqStore, labelService)
|
listService := pullreq.ProvideListService(transactor, gitInterface, authorizer, spaceStore, repoStore, repoGitInfoCache, pullReqStore, labelService)
|
||||||
exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer)
|
exporterRepository, err := exporter.ProvideSpaceExporter(provider, gitInterface, repoStore, jobScheduler, executor, encrypter, streamer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -14,12 +14,23 @@
|
|||||||
|
|
||||||
package types
|
package types
|
||||||
|
|
||||||
|
import "github.com/harness/gitness/git/sha"
|
||||||
|
|
||||||
type Branch struct {
|
type Branch struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
SHA string `json:"sha"`
|
SHA sha.SHA `json:"sha"`
|
||||||
Commit *Commit `json:"commit,omitempty"`
|
Commit *Commit `json:"commit,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BranchExtended struct {
|
||||||
|
Branch
|
||||||
|
IsDefault bool `json:"is_default"`
|
||||||
|
CheckSummary *CheckCountSummary `json:"check_summary,omitempty"`
|
||||||
|
Rules []RuleInfo `json:"rules,omitempty"`
|
||||||
|
PullRequests []*PullReq `json:"pull_requests,omitempty"`
|
||||||
|
CommitDivergence *CommitDivergence `json:"commit_divergence,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
type CreateBranchOutput struct {
|
type CreateBranchOutput struct {
|
||||||
Branch
|
Branch
|
||||||
DryRunRulesOutput
|
DryRunRulesOutput
|
||||||
@ -28,3 +39,11 @@ type CreateBranchOutput struct {
|
|||||||
type DeleteBranchOutput struct {
|
type DeleteBranchOutput struct {
|
||||||
DryRunRulesOutput
|
DryRunRulesOutput
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// CommitDivergence contains the information of the count of converging commits between two refs.
|
||||||
|
type CommitDivergence struct {
|
||||||
|
// Ahead is the count of commits the 'From' ref is ahead of the 'To' ref.
|
||||||
|
Ahead int32 `json:"ahead"`
|
||||||
|
// Behind is the count of commits the 'From' ref is behind the 'To' ref.
|
||||||
|
Behind int32 `json:"behind"`
|
||||||
|
}
|
||||||
|
@ -109,3 +109,11 @@ type PullReqCheck struct {
|
|||||||
Bypassable bool `json:"bypassable"`
|
Bypassable bool `json:"bypassable"`
|
||||||
Check Check `json:"check"`
|
Check Check `json:"check"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CheckCountSummary struct {
|
||||||
|
Pending int `json:"pending"`
|
||||||
|
Running int `json:"running"`
|
||||||
|
Success int `json:"success"`
|
||||||
|
Failure int `json:"failure"`
|
||||||
|
Error int `json:"error"`
|
||||||
|
}
|
||||||
|
19
types/git.go
19
types/git.go
@ -40,13 +40,22 @@ type CommitFilter struct {
|
|||||||
IncludeStats bool `json:"include_stats"`
|
IncludeStats bool `json:"include_stats"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type BranchMetadataOptions struct {
|
||||||
|
IncludeChecks bool `json:"include_checks"`
|
||||||
|
IncludeRules bool `json:"include_rules"`
|
||||||
|
IncludePullReqs bool `json:"include_pullreqs"`
|
||||||
|
MaxDivergence int `json:"max_divergence"`
|
||||||
|
}
|
||||||
|
|
||||||
// BranchFilter stores branch query parameters.
|
// BranchFilter stores branch query parameters.
|
||||||
type BranchFilter struct {
|
type BranchFilter struct {
|
||||||
Query string `json:"query"`
|
Query string `json:"query"`
|
||||||
Sort enum.BranchSortOption `json:"sort"`
|
Sort enum.BranchSortOption `json:"sort"`
|
||||||
Order enum.Order `json:"order"`
|
Order enum.Order `json:"order"`
|
||||||
Page int `json:"page"`
|
Page int `json:"page"`
|
||||||
Size int `json:"size"`
|
Size int `json:"size"`
|
||||||
|
IncludeCommit bool `json:"include_commit"`
|
||||||
|
BranchMetadataOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
// TagFilter stores commit tag query parameters.
|
// TagFilter stores commit tag query parameters.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user