mirror of
https://github.com/harness/drone.git
synced 2025-05-09 00:41:18 +08:00
feat: [CODE-2857]: Add checks API to spaces (#3084)
* Fix stmt reassignment * Add get descendent ids helper to space store * Add checks API to spaces
This commit is contained in:
parent
ab9d78dc7b
commit
18da27f968
63
app/api/controller/check/check_recent_space.go
Normal file
63
app/api/controller/check/check_recent_space.go
Normal file
@ -0,0 +1,63 @@
|
||||
// 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 check
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// ListRecentChecksSpace return an array of status check UIDs that have been run recently.
|
||||
func (c *Controller) ListRecentChecksSpace(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
recursive bool,
|
||||
opts types.CheckRecentOptions,
|
||||
) ([]string, error) {
|
||||
space, err := c.getSpaceCheckAccess(ctx, session, spaceRef, enum.PermissionSpaceEdit)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access to space: %w", err)
|
||||
}
|
||||
|
||||
if opts.Since == 0 {
|
||||
opts.Since = time.Now().Add(-30 * 24 * time.Hour).UnixMilli()
|
||||
}
|
||||
|
||||
var spaceIDs []int64
|
||||
if recursive {
|
||||
spaceIDs, err = c.spaceStore.GetDescendantsIDs(ctx, space.ID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get space descendants ids: %w", err)
|
||||
}
|
||||
} else {
|
||||
spaceIDs = append(spaceIDs, space.ID)
|
||||
}
|
||||
|
||||
checkIdentifiers, err := c.checkStore.ListRecentSpace(ctx, spaceIDs, opts)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to list status check results for space=%s: %w",
|
||||
space.Identifier, err,
|
||||
)
|
||||
}
|
||||
|
||||
return checkIdentifiers, nil
|
||||
}
|
@ -33,6 +33,7 @@ type Controller struct {
|
||||
tx dbtx.Transactor
|
||||
authorizer authz.Authorizer
|
||||
repoStore store.RepoStore
|
||||
spaceStore store.SpaceStore
|
||||
checkStore store.CheckStore
|
||||
git git.Interface
|
||||
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error
|
||||
@ -42,6 +43,7 @@ func NewController(
|
||||
tx dbtx.Transactor,
|
||||
authorizer authz.Authorizer,
|
||||
repoStore store.RepoStore,
|
||||
spaceStore store.SpaceStore,
|
||||
checkStore store.CheckStore,
|
||||
git git.Interface,
|
||||
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error,
|
||||
@ -50,6 +52,7 @@ func NewController(
|
||||
tx: tx,
|
||||
authorizer: authorizer,
|
||||
repoStore: repoStore,
|
||||
spaceStore: spaceStore,
|
||||
checkStore: checkStore,
|
||||
git: git,
|
||||
sanitizers: sanitizers,
|
||||
@ -74,3 +77,24 @@ func (c *Controller) getRepoCheckAccess(ctx context.Context,
|
||||
|
||||
return repo, nil
|
||||
}
|
||||
|
||||
func (c *Controller) getSpaceCheckAccess(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
spaceRef string,
|
||||
permission enum.Permission,
|
||||
) (*types.Space, error) {
|
||||
space, err := c.spaceStore.FindByRef(ctx, spaceRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("parent space not found: %w", err)
|
||||
}
|
||||
|
||||
scope := &types.Scope{SpacePath: space.Path}
|
||||
resource := &types.Resource{Type: enum.ResourceTypeRepo}
|
||||
err = apiauth.Check(ctx, c.authorizer, session, scope, resource, permission)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("auth check failed: %w", err)
|
||||
}
|
||||
|
||||
return space, nil
|
||||
}
|
||||
|
@ -35,6 +35,7 @@ func ProvideController(
|
||||
tx dbtx.Transactor,
|
||||
authorizer authz.Authorizer,
|
||||
repoStore store.RepoStore,
|
||||
spaceStore store.SpaceStore,
|
||||
checkStore store.CheckStore,
|
||||
rpcClient git.Interface,
|
||||
sanitizers map[enum.CheckPayloadKind]func(in *ReportInput, s *auth.Session) error,
|
||||
@ -43,6 +44,7 @@ func ProvideController(
|
||||
tx,
|
||||
authorizer,
|
||||
repoStore,
|
||||
spaceStore,
|
||||
checkStore,
|
||||
rpcClient,
|
||||
sanitizers,
|
||||
|
59
app/api/handler/check/check_recent_space.go
Normal file
59
app/api/handler/check/check_recent_space.go
Normal file
@ -0,0 +1,59 @@
|
||||
// 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 pullreq
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/controller/check"
|
||||
"github.com/harness/gitness/app/api/render"
|
||||
"github.com/harness/gitness/app/api/request"
|
||||
)
|
||||
|
||||
// HandleCheckListRecentSpace is an HTTP handler for listing recently executed status checks for a space.
|
||||
func HandleCheckListRecentSpace(checkCtrl *check.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
spaceRef, err := request.GetSpaceRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
opts, err := request.ParseCheckRecentOptions(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
recursive, err := request.ParseRecursiveFromQuery(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
checkIdentifiers, err := checkCtrl.ListRecentChecksSpace(
|
||||
ctx, session, spaceRef, recursive, opts,
|
||||
)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, checkIdentifiers)
|
||||
}
|
||||
}
|
@ -222,7 +222,7 @@ func setupRoutesV1WithAuth(r chi.Router,
|
||||
capabilitiesCtrl *capabilities.Controller,
|
||||
) {
|
||||
setupAccountWithAuth(r, userCtrl, config)
|
||||
setupSpaces(r, appCtx, spaceCtrl, userGroupCtrl, webhookCtrl)
|
||||
setupSpaces(r, appCtx, spaceCtrl, userGroupCtrl, webhookCtrl, checkCtrl)
|
||||
setupRepos(r, repoCtrl, repoSettingsCtrl, pipelineCtrl, executionCtrl, triggerCtrl,
|
||||
logCtrl, pullreqCtrl, webhookCtrl, checkCtrl, uploadCtrl)
|
||||
setupConnectors(r, connectorCtrl)
|
||||
@ -248,7 +248,7 @@ func setupSpaces(
|
||||
spaceCtrl *space.Controller,
|
||||
userGroupCtrl *usergroup.Controller,
|
||||
webhookCtrl *webhook.Controller,
|
||||
|
||||
checkCtrl *check.Controller,
|
||||
) {
|
||||
r.Route("/spaces", func(r chi.Router) {
|
||||
// Create takes path and parentId via body, not uri
|
||||
@ -294,6 +294,8 @@ func setupSpaces(
|
||||
SetupSpaceLabels(r, spaceCtrl)
|
||||
SetupWebhookSpace(r, webhookCtrl)
|
||||
SetupRulesSpace(r, spaceCtrl)
|
||||
|
||||
r.Get("/checks", handlercheck.HandleCheckListRecentSpace(checkCtrl))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -196,6 +196,9 @@ type (
|
||||
// GetDescendantsData returns a list of space parent data for spaces that are descendants of the space.
|
||||
GetDescendantsData(ctx context.Context, spaceID int64) ([]types.SpaceParentData, error)
|
||||
|
||||
// GetDescendantsIDs returns a list of space ids for spaces that are descendants of the specified space.
|
||||
GetDescendantsIDs(ctx context.Context, spaceID int64) ([]int64, error)
|
||||
|
||||
// Create creates a new space
|
||||
Create(ctx context.Context, space *types.Space) error
|
||||
|
||||
@ -646,7 +649,19 @@ type (
|
||||
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, opts types.CheckRecentOptions) ([]string, error)
|
||||
ListRecent(
|
||||
ctx context.Context,
|
||||
repoID int64,
|
||||
opts types.CheckRecentOptions,
|
||||
) ([]string, error)
|
||||
|
||||
// ListRecentSpace returns a list of recently executed status checks in
|
||||
// repositories in spaces with specified space IDs.
|
||||
ListRecentSpace(
|
||||
ctx context.Context,
|
||||
spaceIDs []int64,
|
||||
opts types.CheckRecentOptions,
|
||||
) ([]string, error)
|
||||
|
||||
// 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)
|
||||
|
@ -248,16 +248,42 @@ func (s *CheckStore) List(ctx context.Context,
|
||||
}
|
||||
|
||||
// ListRecent returns a list of recently executed status checks in a repository.
|
||||
func (s *CheckStore) ListRecent(ctx context.Context,
|
||||
func (s *CheckStore) ListRecent(
|
||||
ctx context.Context,
|
||||
repoID int64,
|
||||
opts types.CheckRecentOptions,
|
||||
) ([]string, error) {
|
||||
stmt := database.Builder.
|
||||
Select("distinct check_uid").
|
||||
From("checks").
|
||||
Where("check_repo_id = ?", repoID).
|
||||
Where("check_created > ?", opts.Since)
|
||||
Where("check_created > ?", opts.Since).
|
||||
Where("check_repo_id = ?", repoID)
|
||||
|
||||
return s.listRecent(ctx, stmt, opts)
|
||||
}
|
||||
|
||||
// ListRecentSpace returns a list of recently executed status checks in
|
||||
// repositories in spaces with specified space IDs.
|
||||
func (s *CheckStore) ListRecentSpace(
|
||||
ctx context.Context,
|
||||
spaceIDs []int64,
|
||||
opts types.CheckRecentOptions,
|
||||
) ([]string, error) {
|
||||
stmt := database.Builder.
|
||||
Select("distinct check_uid").
|
||||
From("checks").
|
||||
Join("repositories ON checks.check_repo_id = repositories.repo_id").
|
||||
Where("check_created > ?", opts.Since).
|
||||
Where(squirrel.Eq{"repositories.repo_parent_id": spaceIDs})
|
||||
|
||||
return s.listRecent(ctx, stmt, opts)
|
||||
}
|
||||
|
||||
func (s *CheckStore) listRecent(
|
||||
ctx context.Context,
|
||||
stmt squirrel.SelectBuilder,
|
||||
opts types.CheckRecentOptions,
|
||||
) ([]string, error) {
|
||||
stmt = s.applyOpts(stmt, opts.Query)
|
||||
|
||||
stmt = stmt.OrderBy("check_uid")
|
||||
@ -267,10 +293,9 @@ func (s *CheckStore) ListRecent(ctx context.Context,
|
||||
return nil, fmt.Errorf("failed to convert list recent status checks query to sql: %w", err)
|
||||
}
|
||||
|
||||
dst := make([]string, 0)
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
dst := make([]string, 0)
|
||||
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to execute list recent status checks query")
|
||||
}
|
||||
|
@ -562,15 +562,14 @@ func (s *RepoStore) countAll(
|
||||
parentID int64,
|
||||
filter *types.RepoFilter,
|
||||
) (int64, error) {
|
||||
query := spaceDescendantsQuery + `
|
||||
SELECT space_descendant_id
|
||||
FROM space_descendants`
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
var spaceIDs []int64
|
||||
if err := db.SelectContext(ctx, &spaceIDs, query, parentID); err != nil {
|
||||
return 0, database.ProcessSQLErrorf(ctx, err, "failed to retrieve spaces")
|
||||
spaceIDs, err := getSpaceDescendantsIDs(ctx, db, parentID)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf(
|
||||
"failed to get space descendants ids for %d: %w",
|
||||
parentID, err,
|
||||
)
|
||||
}
|
||||
|
||||
stmt := database.Builder.
|
||||
@ -691,15 +690,14 @@ func (s *RepoStore) listAll(
|
||||
parentID int64,
|
||||
filter *types.RepoFilter,
|
||||
) ([]*types.Repository, error) {
|
||||
query := spaceDescendantsQuery + `
|
||||
SELECT space_descendant_id
|
||||
FROM space_descendants`
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
var spaceIDs []int64
|
||||
if err := db.SelectContext(ctx, &spaceIDs, query, parentID); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "failed to retrieve spaces")
|
||||
spaceIDs, err := getSpaceDescendantsIDs(ctx, db, parentID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf(
|
||||
"failed to get space descendants ids for %d: %w",
|
||||
parentID, err,
|
||||
)
|
||||
}
|
||||
|
||||
stmt := database.Builder.
|
||||
|
@ -336,6 +336,24 @@ func (s *SpaceStore) GetDescendantsData(ctx context.Context, spaceID int64) ([]t
|
||||
return s.readParentsData(ctx, query, spaceID)
|
||||
}
|
||||
|
||||
// GetDescendantsIDs returns a list of space ids for spaces that are descendants of the specified space.
|
||||
func (s *SpaceStore) GetDescendantsIDs(ctx context.Context, spaceID int64) ([]int64, error) {
|
||||
return getSpaceDescendantsIDs(ctx, dbtx.GetAccessor(ctx, s.db), spaceID)
|
||||
}
|
||||
|
||||
func getSpaceDescendantsIDs(ctx context.Context, db dbtx.Accessor, spaceID int64) ([]int64, error) {
|
||||
query := spaceDescendantsQuery + `
|
||||
SELECT space_descendant_id
|
||||
FROM space_descendants`
|
||||
|
||||
var ids []int64
|
||||
if err := db.SelectContext(ctx, &ids, query, spaceID); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "failed to retrieve spaces")
|
||||
}
|
||||
|
||||
return ids, nil
|
||||
}
|
||||
|
||||
func (s *SpaceStore) readParentsData(
|
||||
ctx context.Context,
|
||||
query string,
|
||||
|
@ -406,7 +406,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
||||
principalController := principal.ProvideController(principalStore, authorizer)
|
||||
usergroupController := usergroup2.ProvideController(userGroupStore, spaceStore, authorizer, searchService)
|
||||
v := check2.ProvideCheckSanitizers()
|
||||
checkController := check2.ProvideController(transactor, authorizer, repoStore, checkStore, gitInterface, v)
|
||||
checkController := check2.ProvideController(transactor, authorizer, repoStore, spaceStore, checkStore, gitInterface, v)
|
||||
systemController := system.NewController(principalStore, config)
|
||||
blobConfig, err := server.ProvideBlobStoreConfig(config)
|
||||
if err != nil {
|
||||
|
Loading…
Reference in New Issue
Block a user