mirror of https://github.com/harness/drone.git
298 lines
8.5 KiB
Go
298 lines
8.5 KiB
Go
// 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 database
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/harness/gitness/app/store"
|
|
"github.com/harness/gitness/store/database"
|
|
"github.com/harness/gitness/store/database/dbtx"
|
|
"github.com/harness/gitness/types"
|
|
"github.com/harness/gitness/types/enum"
|
|
|
|
"github.com/Masterminds/squirrel"
|
|
"github.com/gotidy/ptr"
|
|
"github.com/guregu/null"
|
|
"github.com/jmoiron/sqlx"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
var _ store.PullReqLabelAssignmentStore = (*pullReqLabelStore)(nil)
|
|
|
|
func NewPullReqLabelStore(db *sqlx.DB) store.PullReqLabelAssignmentStore {
|
|
return &pullReqLabelStore{
|
|
db: db,
|
|
}
|
|
}
|
|
|
|
type pullReqLabelStore struct {
|
|
db *sqlx.DB
|
|
}
|
|
|
|
type pullReqLabel struct {
|
|
PullReqID int64 `db:"pullreq_label_pullreq_id"`
|
|
LabelID int64 `db:"pullreq_label_label_id"`
|
|
LabelValueID null.Int `db:"pullreq_label_label_value_id"`
|
|
Created int64 `db:"pullreq_label_created"`
|
|
Updated int64 `db:"pullreq_label_updated"`
|
|
CreatedBy int64 `db:"pullreq_label_created_by"`
|
|
UpdatedBy int64 `db:"pullreq_label_updated_by"`
|
|
}
|
|
|
|
type pullReqAssignmentInfo struct {
|
|
PullReqID int64 `db:"pullreq_label_pullreq_id"`
|
|
LabelID int64 `db:"label_id"`
|
|
LabelKey string `db:"label_key"`
|
|
LabelColor enum.LabelColor `db:"label_color"`
|
|
LabelScope int64 `db:"label_scope"`
|
|
ValueCount int64 `db:"label_value_count"`
|
|
ValueID null.Int `db:"label_value_id"`
|
|
Value null.String `db:"label_value_value"`
|
|
ValueColor null.String `db:"label_value_color"` // get's converted to *enum.LabelColor
|
|
}
|
|
|
|
const (
|
|
pullReqLabelColumns = `
|
|
pullreq_label_pullreq_id
|
|
,pullreq_label_label_id
|
|
,pullreq_label_label_value_id
|
|
,pullreq_label_created
|
|
,pullreq_label_updated
|
|
,pullreq_label_created_by
|
|
,pullreq_label_updated_by`
|
|
)
|
|
|
|
func (s *pullReqLabelStore) Assign(ctx context.Context, label *types.PullReqLabel) error {
|
|
const sqlQuery = `
|
|
INSERT INTO pullreq_labels (` + pullReqLabelColumns + `)
|
|
values (
|
|
:pullreq_label_pullreq_id
|
|
,:pullreq_label_label_id
|
|
,:pullreq_label_label_value_id
|
|
,:pullreq_label_created
|
|
,:pullreq_label_updated
|
|
,:pullreq_label_created_by
|
|
,:pullreq_label_updated_by
|
|
)
|
|
ON CONFLICT (pullreq_label_pullreq_id, pullreq_label_label_id)
|
|
DO UPDATE SET
|
|
pullreq_label_label_value_id = EXCLUDED.pullreq_label_label_value_id,
|
|
pullreq_label_updated = EXCLUDED.pullreq_label_updated,
|
|
pullreq_label_updated_by = EXCLUDED.pullreq_label_updated_by
|
|
RETURNING pullreq_label_created, pullreq_label_created_by
|
|
`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
query, args, err := db.BindNamed(sqlQuery, mapInternalPullReqLabel(label))
|
|
if err != nil {
|
|
return database.ProcessSQLErrorf(ctx, err, "failed to bind query")
|
|
}
|
|
|
|
if err = db.QueryRowContext(ctx, query, args...).Scan(&label.Created, &label.CreatedBy); err != nil {
|
|
return database.ProcessSQLErrorf(ctx, err, "failed to create pull request label")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *pullReqLabelStore) Unassign(ctx context.Context, pullreqID int64, labelID int64) error {
|
|
const sqlQuery = `
|
|
DELETE FROM pullreq_labels
|
|
WHERE pullreq_label_pullreq_id = $1 AND pullreq_label_label_id = $2`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
if _, err := db.ExecContext(ctx, sqlQuery, pullreqID, labelID); err != nil {
|
|
return database.ProcessSQLErrorf(ctx, err, "failed to delete pullreq label")
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *pullReqLabelStore) FindByLabelID(
|
|
ctx context.Context,
|
|
pullreqID int64,
|
|
labelID int64,
|
|
) (*types.PullReqLabel, error) {
|
|
const sqlQuery = `SELECT ` + pullReqLabelColumns + `
|
|
FROM pullreq_labels
|
|
WHERE pullreq_label_pullreq_id = $1 AND pullreq_label_label_id = $2`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
var dst pullReqLabel
|
|
if err := db.GetContext(ctx, &dst, sqlQuery, pullreqID, labelID); err != nil {
|
|
return nil, database.ProcessSQLErrorf(ctx, err, "failed to find pullreq label by id")
|
|
}
|
|
|
|
return mapPullReqLabel(&dst), nil
|
|
}
|
|
|
|
func (s *pullReqLabelStore) ListAssigned(
|
|
ctx context.Context,
|
|
pullreqID int64,
|
|
) (map[int64]*types.LabelAssignment, error) {
|
|
const sqlQuery = `
|
|
SELECT
|
|
label_id
|
|
,label_repo_id
|
|
,label_space_id
|
|
,label_key
|
|
,label_value_id
|
|
,label_value_label_id
|
|
,label_value_value
|
|
,label_color
|
|
,label_value_color
|
|
,label_scope
|
|
,label_type
|
|
FROM pullreq_labels
|
|
INNER JOIN labels ON pullreq_label_label_id = label_id
|
|
LEFT JOIN label_values ON pullreq_label_label_value_id = label_value_id
|
|
WHERE pullreq_label_pullreq_id = $1`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
var dst []*struct {
|
|
labelInfo
|
|
labelValueInfo
|
|
}
|
|
if err := db.SelectContext(ctx, &dst, sqlQuery, pullreqID); err != nil {
|
|
return nil, database.ProcessSQLErrorf(ctx, err, "failed to list assigned label")
|
|
}
|
|
|
|
ret := make(map[int64]*types.LabelAssignment, len(dst))
|
|
for _, res := range dst {
|
|
li := mapLabelInfo(&res.labelInfo)
|
|
lvi := mapLabeValuelInfo(&res.labelValueInfo)
|
|
ret[li.ID] = &types.LabelAssignment{
|
|
LabelInfo: *li,
|
|
AssignedValue: lvi,
|
|
}
|
|
}
|
|
|
|
return ret, nil
|
|
}
|
|
|
|
func (s *pullReqLabelStore) ListAssignedByPullreqIDs(
|
|
ctx context.Context,
|
|
pullreqIDs []int64,
|
|
) (map[int64][]*types.LabelPullReqAssignmentInfo, error) {
|
|
stmt := database.Builder.Select(`
|
|
pullreq_label_pullreq_id
|
|
,label_id
|
|
,label_key
|
|
,label_color
|
|
,label_scope
|
|
,label_value_count
|
|
,label_value_id
|
|
,label_value_value
|
|
,label_value_color
|
|
`).
|
|
From("pullreq_labels").
|
|
InnerJoin("labels ON pullreq_label_label_id = label_id").
|
|
LeftJoin("label_values ON pullreq_label_label_value_id = label_value_id").
|
|
Where(squirrel.Eq{"pullreq_label_pullreq_id": pullreqIDs})
|
|
|
|
sql, args, err := stmt.ToSql()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "Failed to convert query to sql")
|
|
}
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
var dst []*pullReqAssignmentInfo
|
|
if err := db.SelectContext(ctx, &dst, sql, args...); err != nil {
|
|
return nil, database.ProcessSQLErrorf(ctx, err, "failed to list assigned label")
|
|
}
|
|
|
|
return mapPullReqAssignmentInfos(dst), nil
|
|
}
|
|
|
|
func (s *pullReqLabelStore) FindValueByLabelID(
|
|
ctx context.Context,
|
|
pullreqID int64,
|
|
labelID int64,
|
|
) (*types.LabelValue, error) {
|
|
const sqlQuery = `SELECT label_value_id, ` + labelValueColumns + `
|
|
FROM pullreq_labels
|
|
JOIN label_values ON pullreq_label_label_value_id = label_value_id
|
|
WHERE pullreq_label_pullreq_id = $1 AND pullreq_label_label_id = $2`
|
|
|
|
db := dbtx.GetAccessor(ctx, s.db)
|
|
|
|
var dst labelValue
|
|
if err := db.GetContext(ctx, &dst, sqlQuery, pullreqID, labelID); err != nil {
|
|
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find label")
|
|
}
|
|
|
|
return mapLabelValue(&dst), nil
|
|
}
|
|
|
|
func mapInternalPullReqLabel(lbl *types.PullReqLabel) *pullReqLabel {
|
|
return &pullReqLabel{
|
|
PullReqID: lbl.PullReqID,
|
|
LabelID: lbl.LabelID,
|
|
LabelValueID: null.IntFromPtr(lbl.ValueID),
|
|
Created: lbl.Created,
|
|
Updated: lbl.Updated,
|
|
CreatedBy: lbl.CreatedBy,
|
|
UpdatedBy: lbl.UpdatedBy,
|
|
}
|
|
}
|
|
|
|
func mapPullReqLabel(lbl *pullReqLabel) *types.PullReqLabel {
|
|
return &types.PullReqLabel{
|
|
PullReqID: lbl.PullReqID,
|
|
LabelID: lbl.LabelID,
|
|
ValueID: lbl.LabelValueID.Ptr(),
|
|
Created: lbl.Created,
|
|
Updated: lbl.Updated,
|
|
CreatedBy: lbl.CreatedBy,
|
|
UpdatedBy: lbl.UpdatedBy,
|
|
}
|
|
}
|
|
|
|
func mapPullReqAssignmentInfo(lbl *pullReqAssignmentInfo) *types.LabelPullReqAssignmentInfo {
|
|
var valueColor *enum.LabelColor
|
|
if lbl.ValueColor.Valid {
|
|
valueColor = ptr.Of(enum.LabelColor(lbl.ValueColor.String))
|
|
}
|
|
return &types.LabelPullReqAssignmentInfo{
|
|
PullReqID: lbl.PullReqID,
|
|
LabelID: lbl.LabelID,
|
|
LabelKey: lbl.LabelKey,
|
|
LabelColor: lbl.LabelColor,
|
|
LabelScope: lbl.LabelScope,
|
|
ValueCount: lbl.ValueCount,
|
|
ValueID: lbl.ValueID.Ptr(),
|
|
Value: lbl.Value.Ptr(),
|
|
ValueColor: valueColor,
|
|
}
|
|
}
|
|
|
|
func mapPullReqAssignmentInfos(
|
|
dbLabels []*pullReqAssignmentInfo,
|
|
) map[int64][]*types.LabelPullReqAssignmentInfo {
|
|
result := make(map[int64][]*types.LabelPullReqAssignmentInfo)
|
|
|
|
for _, lbl := range dbLabels {
|
|
result[lbl.PullReqID] = append(result[lbl.PullReqID], mapPullReqAssignmentInfo(lbl))
|
|
}
|
|
|
|
return result
|
|
}
|