mirror of
https://github.com/harness/drone.git
synced 2025-05-06 20:31:01 +08:00
260 lines
8.0 KiB
Go
260 lines
8.0 KiB
Go
// Copyright 2022 Harness Inc. All rights reserved.
|
|
// Use of this source code is governed by the Polyform Free Trial License
|
|
// that can be found in the LICENSE.md file for this repository.
|
|
|
|
package database
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/harness/gitness/internal/store"
|
|
"github.com/harness/gitness/internal/store/database/dbtx"
|
|
"github.com/harness/gitness/types"
|
|
"github.com/harness/gitness/types/enum"
|
|
|
|
"github.com/guregu/null"
|
|
"github.com/jmoiron/sqlx"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var _ store.PullReqReviewerStore = (*PullReqReviewerStore)(nil)
|
|
|
|
const maxPullRequestReviewers = 100
|
|
|
|
// NewPullReqReviewerStore returns a new PullReqReviewerStore.
|
|
func NewPullReqReviewerStore(db *sqlx.DB) *PullReqReviewerStore {
|
|
return &PullReqReviewerStore{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
// PullReqReviewerStore implements store.PullReqReviewerStore backed by a relational database.
|
|
type PullReqReviewerStore struct {
|
|
db *sqlx.DB
|
|
}
|
|
|
|
// pullReqReviewer is used to fetch pull request reviewer data from the database.
|
|
type pullReqReviewer struct {
|
|
PullReqID int64 `db:"pullreq_reviewer_pullreq_id"`
|
|
PrincipalID int64 `db:"pullreq_reviewer_principal_id"`
|
|
CreatedBy int64 `db:"pullreq_reviewer_created_by"`
|
|
Created int64 `db:"pullreq_reviewer_created"`
|
|
Updated int64 `db:"pullreq_reviewer_updated"`
|
|
|
|
RepoID int64 `db:"pullreq_reviewer_repo_id"`
|
|
Type enum.PullReqReviewerType `db:"pullreq_reviewer_type"`
|
|
LatestReviewID null.Int `db:"pullreq_reviewer_latest_review_id"`
|
|
|
|
ReviewDecision enum.PullReqReviewDecision `db:"pullreq_reviewer_review_decision"`
|
|
SHA string `db:"pullreq_reviewer_sha"`
|
|
|
|
ReviewerUID string `db:"reviewer_uid"`
|
|
ReviewerName string `db:"reviewer_name"`
|
|
ReviewerEmail string `db:"reviewer_email"`
|
|
AddedByUID string `db:"added_by_uid"`
|
|
AddedByName string `db:"added_by_name"`
|
|
AddedByEmail string `db:"added_by_email"`
|
|
}
|
|
|
|
const (
|
|
pullreqReviewerColumns = `
|
|
pullreq_reviewer_pullreq_id
|
|
,pullreq_reviewer_principal_id
|
|
,pullreq_reviewer_created_by
|
|
,pullreq_reviewer_created
|
|
,pullreq_reviewer_updated
|
|
,pullreq_reviewer_repo_id
|
|
,pullreq_reviewer_type
|
|
,pullreq_reviewer_latest_review_id
|
|
,pullreq_reviewer_review_decision
|
|
,pullreq_reviewer_sha
|
|
,reviewer.principal_uid as "reviewer_uid"
|
|
,reviewer.principal_display_name as "reviewer_name"
|
|
,reviewer.principal_email as "reviewer_email"
|
|
,added_by.principal_uid as "added_by_uid"
|
|
,added_by.principal_display_name as "added_by_name"
|
|
,added_by.principal_email as "added_by_email"`
|
|
|
|
pullreqReviewerSelectBase = `
|
|
SELECT` + pullreqReviewerColumns + `
|
|
FROM pullreq_reviewers
|
|
INNER JOIN principals reviewer on reviewer.principal_id = pullreq_reviewer_principal_id
|
|
INNER JOIN principals added_by on added_by.principal_id = pullreq_reviewer_created_by`
|
|
)
|
|
|
|
// Find finds the pull request reviewer by pull request id and principal id.
|
|
func (s *PullReqReviewerStore) Find(ctx context.Context, prID, principalID int64) (*types.PullReqReviewer, error) {
|
|
const sqlQuery = pullreqReviewerSelectBase + `
|
|
WHERE pullreq_reviewer_pullreq_id = $1 AND pullreq_reviewer_principal_id = $2`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
dst := &pullReqReviewer{}
|
|
if err := db.GetContext(ctx, dst, sqlQuery, prID, principalID); err != nil {
|
|
return nil, processSQLErrorf(err, "Failed to find pull request reviewer")
|
|
}
|
|
|
|
return mapPullReqReviewer(dst), nil
|
|
}
|
|
|
|
// Create creates a new pull request reviewer.
|
|
func (s *PullReqReviewerStore) Create(ctx context.Context, v *types.PullReqReviewer) error {
|
|
const sqlQuery = `
|
|
INSERT INTO pullreq_reviewers (
|
|
pullreq_reviewer_pullreq_id
|
|
,pullreq_reviewer_principal_id
|
|
,pullreq_reviewer_created_by
|
|
,pullreq_reviewer_created
|
|
,pullreq_reviewer_updated
|
|
,pullreq_reviewer_repo_id
|
|
,pullreq_reviewer_type
|
|
,pullreq_reviewer_latest_review_id
|
|
,pullreq_reviewer_review_decision
|
|
,pullreq_reviewer_sha
|
|
) values (
|
|
:pullreq_reviewer_pullreq_id
|
|
,:pullreq_reviewer_principal_id
|
|
,:pullreq_reviewer_created_by
|
|
,:pullreq_reviewer_created
|
|
,:pullreq_reviewer_updated
|
|
,:pullreq_reviewer_repo_id
|
|
,:pullreq_reviewer_type
|
|
,:pullreq_reviewer_latest_review_id
|
|
,:pullreq_reviewer_review_decision
|
|
,:pullreq_reviewer_sha
|
|
)`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
query, arg, err := db.BindNamed(sqlQuery, mapInternalPullReqReviewer(v))
|
|
if err != nil {
|
|
return processSQLErrorf(err, "Failed to bind pull request reviewer object")
|
|
}
|
|
|
|
if _, err = db.ExecContext(ctx, query, arg...); err != nil {
|
|
return processSQLErrorf(err, "Failed to insert pull request reviewer")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Update updates the pull request reviewer.
|
|
func (s *PullReqReviewerStore) Update(ctx context.Context, v *types.PullReqReviewer) error {
|
|
const sqlQuery = `
|
|
UPDATE pullreq_reviewers
|
|
SET
|
|
pullreq_reviewer_updated = :pullreq_reviewer_updated
|
|
,pullreq_reviewer_latest_review_id = :pullreq_reviewer_latest_review_id
|
|
,pullreq_reviewer_review_decision = :pullreq_reviewer_review_decision
|
|
,pullreq_reviewer_sha = :pullreq_reviewer_sha
|
|
WHERE pullreq_reviewer_pullreq_id = :pullreq_reviewer_pullreq_id AND
|
|
pullreq_reviewer_principal_id = :pullreq_reviewer_principal_id`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
updatedAt := time.Now()
|
|
|
|
dbv := mapInternalPullReqReviewer(v)
|
|
dbv.Updated = updatedAt.UnixMilli()
|
|
|
|
query, arg, err := db.BindNamed(sqlQuery, dbv)
|
|
if err != nil {
|
|
return processSQLErrorf(err, "Failed to bind pull request activity object")
|
|
}
|
|
|
|
_, err = db.ExecContext(ctx, query, arg...)
|
|
if err != nil {
|
|
return processSQLErrorf(err, "Failed to update pull request activity")
|
|
}
|
|
|
|
v.Updated = dbv.Updated
|
|
|
|
return nil
|
|
}
|
|
|
|
// List returns a list of pull reviewers for a pull request.
|
|
func (s *PullReqReviewerStore) List(ctx context.Context, prID int64) ([]*types.PullReqReviewer, error) {
|
|
stmt := builder.
|
|
Select(pullreqReviewerColumns).
|
|
From("pullreq_reviewers").
|
|
InnerJoin("principals reviewer on reviewer.principal_id = pullreq_reviewer_principal_id").
|
|
LeftJoin("principals added_by on added_by.principal_id = pullreq_reviewer_created_by").
|
|
Where("pullreq_reviewer_pullreq_id = ?", prID).
|
|
OrderBy("pullreq_reviewer_created asc").
|
|
Limit(maxPullRequestReviewers) // memory safety limit
|
|
|
|
sql, args, err := stmt.ToSql()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Failed to convert pull request reviewer list query to sql")
|
|
}
|
|
|
|
dst := make([]*pullReqReviewer, 0)
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
|
|
return nil, processSQLErrorf(err, "Failed executing pull request reviewer list query")
|
|
}
|
|
|
|
return mapSlicePullReqReviewer(dst), nil
|
|
}
|
|
|
|
func mapPullReqReviewer(v *pullReqReviewer) *types.PullReqReviewer {
|
|
m := &types.PullReqReviewer{
|
|
PullReqID: v.PullReqID,
|
|
PrincipalID: v.PrincipalID,
|
|
CreatedBy: v.CreatedBy,
|
|
Created: v.Created,
|
|
Updated: v.Updated,
|
|
RepoID: v.RepoID,
|
|
Type: v.Type,
|
|
LatestReviewID: v.LatestReviewID.Ptr(),
|
|
ReviewDecision: v.ReviewDecision,
|
|
SHA: v.SHA,
|
|
Reviewer: types.PrincipalInfo{
|
|
ID: v.PrincipalID,
|
|
UID: v.ReviewerUID,
|
|
DisplayName: v.ReviewerName,
|
|
Email: v.ReviewerEmail,
|
|
},
|
|
AddedBy: types.PrincipalInfo{
|
|
ID: v.CreatedBy,
|
|
UID: v.AddedByUID,
|
|
DisplayName: v.AddedByName,
|
|
Email: v.AddedByEmail,
|
|
},
|
|
}
|
|
return m
|
|
}
|
|
|
|
func mapInternalPullReqReviewer(v *types.PullReqReviewer) *pullReqReviewer {
|
|
m := &pullReqReviewer{
|
|
PullReqID: v.PullReqID,
|
|
PrincipalID: v.PrincipalID,
|
|
CreatedBy: v.CreatedBy,
|
|
Created: v.Created,
|
|
Updated: v.Updated,
|
|
RepoID: v.RepoID,
|
|
Type: v.Type,
|
|
LatestReviewID: null.IntFromPtr(v.LatestReviewID),
|
|
ReviewDecision: v.ReviewDecision,
|
|
SHA: v.SHA,
|
|
ReviewerUID: "",
|
|
ReviewerName: "",
|
|
ReviewerEmail: "",
|
|
AddedByUID: "",
|
|
AddedByName: "",
|
|
AddedByEmail: "",
|
|
}
|
|
return m
|
|
}
|
|
|
|
func mapSlicePullReqReviewer(a []*pullReqReviewer) []*types.PullReqReviewer {
|
|
m := make([]*types.PullReqReviewer, len(a))
|
|
for i, act := range a {
|
|
m[i] = mapPullReqReviewer(act)
|
|
}
|
|
return m
|
|
}
|