Merge branch 'mg/spaces/list-pagination' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#257)

This commit is contained in:
Marko Gacesa 2023-08-01 10:40:30 +00:00 committed by Harness
commit 5fd846fd25
8 changed files with 107 additions and 26 deletions

View File

@ -9,6 +9,7 @@ import (
"fmt"
"github.com/harness/gitness/internal/auth"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)
@ -19,16 +20,32 @@ func (c *Controller) ListChecks(
session *auth.Session,
repoRef string,
commitSHA string,
) ([]*types.Check, error) {
opts types.CheckListOptions,
) ([]types.Check, int, error) {
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionRepoView)
if err != nil {
return nil, fmt.Errorf("failed to acquire access access to repo: %w", err)
return nil, 0, fmt.Errorf("failed to acquire access access to repo: %w", err)
}
list, err := c.checkStore.List(ctx, repo.ID, commitSHA)
var checks []types.Check
var count int
err = dbtx.New(c.db).WithTx(ctx, func(ctx context.Context) (err error) {
count, err = c.checkStore.Count(ctx, repo.ID, commitSHA, opts)
if err != nil {
return nil, fmt.Errorf("failed to list status check results for repo=%s: %w", repo.UID, err)
return fmt.Errorf("failed to count status check results for repo=%s: %w", repo.UID, err)
}
return list, nil
checks, err = c.checkStore.List(ctx, repo.ID, commitSHA, opts)
if err != nil {
return fmt.Errorf("failed to list status check results for repo=%s: %w", repo.UID, err)
}
return nil
})
if err != nil {
return nil, 0, err
}
return checks, count, nil
}

View File

@ -30,12 +30,15 @@ func HandleCheckList(checkCtrl *check.Controller) http.HandlerFunc {
return
}
list, err := checkCtrl.ListChecks(ctx, session, repoRef, commitSHA)
opts := request.ParseCheckListOptions(r)
checks, count, err := checkCtrl.ListChecks(ctx, session, repoRef, commitSHA, opts)
if err != nil {
render.TranslatedUserError(w, err)
return
}
render.JSON(w, http.StatusOK, list)
render.Pagination(r, w, opts.Page, opts.Size, count)
render.JSON(w, http.StatusOK, checks)
}
}

View File

@ -14,24 +14,17 @@ import (
"github.com/swaggest/openapi-go/openapi3"
)
type reportStatusCheckResultRequest struct {
repoRequest
CommitSHA string `path:"commit_sha"`
check.ReportInput
}
type listStatusCheckResultsRequest struct {
repoRequest
CommitSHA string `path:"commit_sha"`
}
func checkOperations(reflector *openapi3.Reflector) {
const tag = "status_checks"
reportStatusCheckResults := openapi3.Operation{}
reportStatusCheckResults.WithTags(tag)
reportStatusCheckResults.WithMapOfAnything(map[string]interface{}{"operationId": "reportStatusCheckResults"})
_ = reflector.SetRequest(&reportStatusCheckResults, new(reportStatusCheckResultRequest), http.MethodPut)
_ = reflector.SetRequest(&reportStatusCheckResults, struct {
repoRequest
CommitSHA string `path:"commit_sha"`
check.ReportInput
}{}, http.MethodPut)
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(types.Check), http.StatusOK)
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(usererror.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(usererror.Error), http.StatusInternalServerError)
@ -42,8 +35,13 @@ func checkOperations(reflector *openapi3.Reflector) {
listStatusCheckResults := openapi3.Operation{}
listStatusCheckResults.WithTags(tag)
listStatusCheckResults.WithParameters(
queryParameterPage, queryParameterLimit)
listStatusCheckResults.WithMapOfAnything(map[string]interface{}{"operationId": "listStatusCheckResults"})
_ = reflector.SetRequest(&listStatusCheckResults, new(listStatusCheckResultsRequest), http.MethodGet)
_ = reflector.SetRequest(&listStatusCheckResults, struct {
repoRequest
CommitSHA string `path:"commit_sha"`
}{}, http.MethodGet)
_ = reflector.SetJSONResponse(&listStatusCheckResults, new([]types.Check), http.StatusOK)
_ = reflector.SetJSONResponse(&listStatusCheckResults, new(usererror.Error), http.StatusBadRequest)
_ = reflector.SetJSONResponse(&listStatusCheckResults, new(usererror.Error), http.StatusInternalServerError)

View File

@ -0,0 +1,19 @@
// 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 request
import (
"net/http"
"github.com/harness/gitness/types"
)
// ParseCheckListOptions extracts the status check list API options from the url.
func ParseCheckListOptions(r *http.Request) types.CheckListOptions {
return types.CheckListOptions{
Page: ParsePage(r),
Size: ParseLimit(r),
}
}

View File

@ -419,8 +419,11 @@ type (
// Upsert creates new or updates an existing status check result.
Upsert(ctx context.Context, check *types.Check) error
// Count counts status check results for a specific commit in a repo.
Count(ctx context.Context, repoID int64, commitSHA string, opts types.CheckListOptions) (int, error)
// List returns a list of status check results for a specific commit in a repo.
List(ctx context.Context, repoID int64, commitSHA string) ([]*types.Check, error)
List(ctx context.Context, repoID int64, commitSHA string, opts types.CheckListOptions) ([]types.Check, error)
// ListRecent returns a list of recently executed status checks in a repository.
ListRecent(ctx context.Context, repoID int64, since time.Time) ([]string, error)

View File

@ -132,13 +132,47 @@ func (s *CheckStore) Upsert(ctx context.Context, check *types.Check) error {
return nil
}
// Count counts status check results for a specific commit in a repo.
func (s *CheckStore) Count(ctx context.Context,
repoID int64,
commitSHA string,
_ types.CheckListOptions,
) (int, error) {
stmt := database.Builder.
Select("count(*)").
From("checks").
Where("check_repo_id = ?", repoID).
Where("check_commit_sha = ?", commitSHA)
sql, args, err := stmt.ToSql()
if err != nil {
return 0, errors.Wrap(err, "Failed to convert query to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
var count int
err = db.QueryRowContext(ctx, sql, args...).Scan(&count)
if err != nil {
return 0, database.ProcessSQLErrorf(err, "Failed to execute count status checks query")
}
return count, nil
}
// List returns a list of status check results for a specific commit in a repo.
func (s *CheckStore) List(ctx context.Context, repoID int64, commitSHA string) ([]*types.Check, error) {
func (s *CheckStore) List(ctx context.Context,
repoID int64,
commitSHA string,
opts types.CheckListOptions,
) ([]types.Check, error) {
stmt := database.Builder.
Select(checkColumns).
From("checks").
Where("check_repo_id = ?", repoID).
Where("check_commit_sha = ?", commitSHA).
Limit(database.Limit(opts.Size)).
Offset(database.Offset(opts.Page, opts.Size)).
OrderBy("check_updated desc")
sql, args, err := stmt.ToSql()
@ -208,8 +242,8 @@ func mapInternalCheck(c *types.Check) *check {
return m
}
func mapCheck(c *check) *types.Check {
return &types.Check{
func mapCheck(c *check) types.Check {
return types.Check{
ID: c.ID,
CreatedBy: c.CreatedBy,
Created: c.Created,
@ -230,7 +264,7 @@ func mapCheck(c *check) *types.Check {
}
}
func (s *CheckStore) mapSliceCheck(ctx context.Context, checks []*check) ([]*types.Check, error) {
func (s *CheckStore) mapSliceCheck(ctx context.Context, checks []*check) ([]types.Check, error) {
// collect all principal IDs
ids := make([]int64, len(checks))
for i, req := range checks {
@ -244,7 +278,7 @@ func (s *CheckStore) mapSliceCheck(ctx context.Context, checks []*check) ([]*typ
}
// attach the principal infos back to the slice items
m := make([]*types.Check, len(checks))
m := make([]types.Check, len(checks))
for i, c := range checks {
m[i] = mapCheck(c)
if reportedBy, ok := infoMap[c.CreatedBy]; ok {

View File

@ -270,6 +270,7 @@ func (s *SpaceStore) Count(ctx context.Context, id int64, opts *types.SpaceFilte
if err != nil {
return 0, database.ProcessSQLErrorf(err, "Failed executing count query")
}
return count, nil
}

View File

@ -33,6 +33,12 @@ type CheckPayload struct {
Data json.RawMessage `json:"data"`
}
// CheckListOptions holds check list query parameters.
type CheckListOptions struct {
Page int `json:"page"`
Size int `json:"size"`
}
type ReqCheck struct {
ID int64 `json:"id"`
CreatedBy int64 `json:"-"` // clients will use "added_by"