mirror of https://github.com/harness/drone.git
add user filters to the pull request list API (#2624)
* add user filters to the pull request list APIpull/3558/head
parent
ccf267f1cc
commit
a2d2ba07aa
|
@ -393,6 +393,71 @@ var queryParameterIncludeDescription = openapi3.ParameterOrRef{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var queryParameterAuthorID = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamAuthorID,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String("Return only pull requests where this user is the author."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeInteger),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterCommenterID = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamCommenterID,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String("Return only pull requests where this user has created at least one comment."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeInteger),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterReviewerID = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamReviewerID,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String("Return only pull requests where this user has been added as a reviewer."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeInteger),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
var queryParameterReviewDecision = openapi3.ParameterOrRef{
|
||||||
|
Parameter: &openapi3.Parameter{
|
||||||
|
Name: request.QueryParamReviewDecision,
|
||||||
|
In: openapi3.ParameterInQuery,
|
||||||
|
Description: ptr.String("Require only this review decision of the reviewer. " +
|
||||||
|
"Requires " + request.QueryParamReviewerID + " parameter."),
|
||||||
|
Required: ptr.Bool(false),
|
||||||
|
Schema: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeArray),
|
||||||
|
Items: &openapi3.SchemaOrRef{
|
||||||
|
Schema: &openapi3.Schema{
|
||||||
|
Type: ptrSchemaType(openapi3.SchemaTypeString),
|
||||||
|
Enum: enum.PullReqReviewDecision("").Enum(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Style: ptr.String(string(openapi3.EncodingStyleForm)),
|
||||||
|
Explode: ptr.Bool(true),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
//nolint:funlen
|
//nolint:funlen
|
||||||
func pullReqOperations(reflector *openapi3.Reflector) {
|
func pullReqOperations(reflector *openapi3.Reflector) {
|
||||||
createPullReq := openapi3.Operation{}
|
createPullReq := openapi3.Operation{}
|
||||||
|
@ -417,7 +482,8 @@ func pullReqOperations(reflector *openapi3.Reflector) {
|
||||||
queryParameterCreatedLt, queryParameterCreatedGt, queryParameterEditedLt, queryParameterEditedGt,
|
queryParameterCreatedLt, queryParameterCreatedGt, queryParameterEditedLt, queryParameterEditedGt,
|
||||||
queryParameterIncludeDescription,
|
queryParameterIncludeDescription,
|
||||||
QueryParameterPage, QueryParameterLimit,
|
QueryParameterPage, QueryParameterLimit,
|
||||||
QueryParameterLabelID, QueryParameterValueID)
|
QueryParameterLabelID, QueryParameterValueID,
|
||||||
|
queryParameterAuthorID, queryParameterCommenterID, queryParameterReviewerID, queryParameterReviewDecision)
|
||||||
_ = reflector.SetRequest(&listPullReq, new(listPullReqRequest), http.MethodGet)
|
_ = reflector.SetRequest(&listPullReq, new(listPullReqRequest), http.MethodGet)
|
||||||
_ = reflector.SetJSONResponse(&listPullReq, new([]types.PullReq), http.StatusOK)
|
_ = reflector.SetJSONResponse(&listPullReq, new([]types.PullReq), http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&listPullReq, new(usererror.Error), http.StatusBadRequest)
|
_ = reflector.SetJSONResponse(&listPullReq, new(usererror.Error), http.StatusBadRequest)
|
||||||
|
|
|
@ -611,7 +611,8 @@ func spaceOperations(reflector *openapi3.Reflector) {
|
||||||
queryParameterCreatedLt, queryParameterCreatedGt, queryParameterEditedLt,
|
queryParameterCreatedLt, queryParameterCreatedGt, queryParameterEditedLt,
|
||||||
queryParameterIncludeDescription, queryParameterIncludeSubspaces,
|
queryParameterIncludeDescription, queryParameterIncludeSubspaces,
|
||||||
QueryParameterLimit,
|
QueryParameterLimit,
|
||||||
QueryParameterLabelID, QueryParameterValueID)
|
QueryParameterLabelID, QueryParameterValueID,
|
||||||
|
queryParameterAuthorID, queryParameterCommenterID, queryParameterReviewerID, queryParameterReviewDecision)
|
||||||
_ = reflector.SetRequest(&listPullReq, new(listPullReqRequest), http.MethodGet)
|
_ = reflector.SetRequest(&listPullReq, new(listPullReqRequest), http.MethodGet)
|
||||||
_ = reflector.SetJSONResponse(&listPullReq, new([]types.PullReq), http.StatusOK)
|
_ = reflector.SetJSONResponse(&listPullReq, new([]types.PullReq), http.StatusOK)
|
||||||
_ = reflector.SetJSONResponse(&listPullReq, new(usererror.Error), http.StatusBadRequest)
|
_ = reflector.SetJSONResponse(&listPullReq, new(usererror.Error), http.StatusBadRequest)
|
||||||
|
|
|
@ -18,6 +18,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/harness/gitness/errors"
|
||||||
"github.com/harness/gitness/types"
|
"github.com/harness/gitness/types"
|
||||||
"github.com/harness/gitness/types/enum"
|
"github.com/harness/gitness/types/enum"
|
||||||
)
|
)
|
||||||
|
@ -28,6 +29,10 @@ const (
|
||||||
PathParamReviewerID = "pullreq_reviewer_id"
|
PathParamReviewerID = "pullreq_reviewer_id"
|
||||||
PathParamUserGroupID = "user_group_id"
|
PathParamUserGroupID = "user_group_id"
|
||||||
|
|
||||||
|
QueryParamAuthorID = "author_id"
|
||||||
|
QueryParamCommenterID = "commenter_id"
|
||||||
|
QueryParamReviewerID = "reviewer_id"
|
||||||
|
QueryParamReviewDecision = "review_decision"
|
||||||
QueryParamIncludeDescription = "include_description"
|
QueryParamIncludeDescription = "include_description"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -70,6 +75,24 @@ func parsePullReqStates(r *http.Request) []enum.PullReqState {
|
||||||
return states
|
return states
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parseReviewDecisions extracts the pull request reviewer decisions from the url.
|
||||||
|
func parseReviewDecisions(r *http.Request) []enum.PullReqReviewDecision {
|
||||||
|
strReviewDecisions, _ := QueryParamList(r, QueryParamReviewDecision)
|
||||||
|
m := make(map[enum.PullReqReviewDecision]struct{}) // use map to eliminate duplicates
|
||||||
|
for _, s := range strReviewDecisions {
|
||||||
|
if state, ok := enum.PullReqReviewDecision(s).Sanitize(); ok {
|
||||||
|
m[state] = struct{}{}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
reviewDecisions := make([]enum.PullReqReviewDecision, 0, len(m))
|
||||||
|
for s := range m {
|
||||||
|
reviewDecisions = append(reviewDecisions, s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return reviewDecisions
|
||||||
|
}
|
||||||
|
|
||||||
// ParsePullReqFilter extracts the pull request query parameter from the url.
|
// ParsePullReqFilter extracts the pull request query parameter from the url.
|
||||||
func ParsePullReqFilter(r *http.Request) (*types.PullReqFilter, error) {
|
func ParsePullReqFilter(r *http.Request) (*types.PullReqFilter, error) {
|
||||||
createdBy, err := QueryParamListAsPositiveInt64(r, QueryParamCreatedBy)
|
createdBy, err := QueryParamListAsPositiveInt64(r, QueryParamCreatedBy)
|
||||||
|
@ -101,6 +124,26 @@ func ParsePullReqFilter(r *http.Request) (*types.PullReqFilter, error) {
|
||||||
return nil, fmt.Errorf("encountered error parsing include description filter: %w", err)
|
return nil, fmt.Errorf("encountered error parsing include description filter: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
authorID, err := QueryParamAsPositiveInt64OrDefault(r, QueryParamAuthorID, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("encountered error parsing author ID filter: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
commenterID, err := QueryParamAsPositiveInt64OrDefault(r, QueryParamCommenterID, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("encountered error parsing commenter ID filter: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reviewerID, err := QueryParamAsPositiveInt64OrDefault(r, QueryParamReviewerID, 0)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("encountered error parsing reviewer ID filter: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
reviewDecisions := parseReviewDecisions(r)
|
||||||
|
if len(reviewDecisions) > 0 && reviewerID <= 0 {
|
||||||
|
return nil, errors.InvalidArgument("Can't use review decisions without providing a reviewer ID")
|
||||||
|
}
|
||||||
|
|
||||||
return &types.PullReqFilter{
|
return &types.PullReqFilter{
|
||||||
Page: ParsePage(r),
|
Page: ParsePage(r),
|
||||||
Size: ParseLimit(r),
|
Size: ParseLimit(r),
|
||||||
|
@ -114,6 +157,10 @@ func ParsePullReqFilter(r *http.Request) (*types.PullReqFilter, error) {
|
||||||
Order: ParseOrder(r),
|
Order: ParseOrder(r),
|
||||||
LabelID: labelID,
|
LabelID: labelID,
|
||||||
ValueID: valueID,
|
ValueID: valueID,
|
||||||
|
AuthorID: authorID,
|
||||||
|
CommenterID: commenterID,
|
||||||
|
ReviewerID: reviewerID,
|
||||||
|
ReviewDecisions: reviewDecisions,
|
||||||
IncludeDescription: includeDescription,
|
IncludeDescription: includeDescription,
|
||||||
CreatedFilter: createdAtFilter,
|
CreatedFilter: createdAtFilter,
|
||||||
EditedFilter: editedAtFilter,
|
EditedFilter: editedAtFilter,
|
||||||
|
|
|
@ -547,7 +547,7 @@ func (s *PullReqStore) listQuery(opts *types.PullReqFilter) squirrel.SelectBuild
|
||||||
columns = pullReqColumns
|
columns = pullReqColumns
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(opts.LabelID) > 0 || len(opts.ValueID) > 0 {
|
if len(opts.LabelID) > 0 || len(opts.ValueID) > 0 || opts.CommenterID > 0 {
|
||||||
stmt = database.Builder.Select("DISTINCT " + columns)
|
stmt = database.Builder.Select("DISTINCT " + columns)
|
||||||
} else {
|
} else {
|
||||||
stmt = database.Builder.Select(columns)
|
stmt = database.Builder.Select(columns)
|
||||||
|
@ -621,6 +621,26 @@ func (*PullReqStore) applyFilter(stmt *squirrel.SelectBuilder, opts *types.PullR
|
||||||
*stmt = stmt.Where(squirrel.NotEq{"pullreq_target_repo_id": opts.RepoIDBlacklist})
|
*stmt = stmt.Where(squirrel.NotEq{"pullreq_target_repo_id": opts.RepoIDBlacklist})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if opts.AuthorID > 0 {
|
||||||
|
*stmt = stmt.Where("pullreq_created_by = ?", opts.AuthorID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.CommenterID > 0 {
|
||||||
|
*stmt = stmt.InnerJoin("pullreq_activities ON pullreq_activity_pullreq_id = pullreq_id")
|
||||||
|
*stmt = stmt.Where("pullreq_activity_deleted IS NULL")
|
||||||
|
*stmt = stmt.Where("(pullreq_activity_kind = 'comment' OR pullreq_activity_kind = 'change-comment')")
|
||||||
|
*stmt = stmt.Where("pullreq_activity_created_by = ?", opts.CommenterID)
|
||||||
|
}
|
||||||
|
|
||||||
|
if opts.ReviewerID > 0 {
|
||||||
|
*stmt = stmt.InnerJoin(
|
||||||
|
fmt.Sprintf("pullreq_reviewers ON "+
|
||||||
|
"pullreq_reviewer_pullreq_id = pullreq_id AND pullreq_reviewer_principal_id = %d", opts.ReviewerID))
|
||||||
|
if len(opts.ReviewDecisions) > 0 {
|
||||||
|
*stmt = stmt.Where(squirrel.Eq{"pullreq_reviewer_review_decision": opts.ReviewDecisions})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// labels
|
// labels
|
||||||
|
|
||||||
if len(opts.LabelID) == 0 && len(opts.ValueID) == 0 {
|
if len(opts.LabelID) == 0 && len(opts.ValueID) == 0 {
|
||||||
|
|
|
@ -108,6 +108,10 @@ type PullReqFilter struct {
|
||||||
Order enum.Order `json:"order"`
|
Order enum.Order `json:"order"`
|
||||||
LabelID []int64 `json:"label_id"`
|
LabelID []int64 `json:"label_id"`
|
||||||
ValueID []int64 `json:"value_id"`
|
ValueID []int64 `json:"value_id"`
|
||||||
|
AuthorID int64 `json:"author_id"`
|
||||||
|
CommenterID int64 `json:"commenter_id"`
|
||||||
|
ReviewerID int64 `json:"reviewer_id"`
|
||||||
|
ReviewDecisions []enum.PullReqReviewDecision `json:"review_decisions"`
|
||||||
IncludeDescription bool `json:"include_description"`
|
IncludeDescription bool `json:"include_description"`
|
||||||
CreatedFilter
|
CreatedFilter
|
||||||
EditedFilter
|
EditedFilter
|
||||||
|
|
Loading…
Reference in New Issue