mirror of
https://github.com/harness/drone.git
synced 2025-05-09 23:40:15 +08:00
Merge branch 'mg/status-checks/api-layer' of _OKE5H2PQKOUfzFFDuD4FA/default/CODE/gitness (#104)
This commit is contained in:
commit
e4ac32f430
@ -23,6 +23,7 @@ import (
|
||||
harnessevents "github.com/harness/gitness/harness/services/events"
|
||||
"github.com/harness/gitness/harness/store"
|
||||
"github.com/harness/gitness/harness/types/check"
|
||||
checkcontroller "github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/controller/githook"
|
||||
"github.com/harness/gitness/internal/api/controller/principal"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
@ -90,6 +91,7 @@ func initSystem(ctx context.Context, config *gitnesstypes.Config) (*system, erro
|
||||
pubsub.WireSet,
|
||||
codecomments.WireSet,
|
||||
gitrpccron.WireSet,
|
||||
checkcontroller.WireSet,
|
||||
)
|
||||
return &system{}, nil
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import (
|
||||
events4 "github.com/harness/gitness/harness/services/events"
|
||||
"github.com/harness/gitness/harness/store"
|
||||
"github.com/harness/gitness/harness/types/check"
|
||||
check2 "github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/controller/githook"
|
||||
"github.com/harness/gitness/internal/api/controller/principal"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
@ -164,7 +165,9 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
||||
return nil, err
|
||||
}
|
||||
githookController := githook.ProvideController(db, authorizer, principalStore, repoStore, eventsReporter)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, accountClient, controller, principalController, spaceController, repoController, pullreqController, webhookController, githookController)
|
||||
checkStore := database.ProvideCheckStore(db, principalInfoCache)
|
||||
checkController := check2.ProvideController(db, authorizer, checkStore, repoStore, gitrpcInterface)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, accountClient, controller, principalController, spaceController, repoController, pullreqController, webhookController, githookController, checkController)
|
||||
gitHandler := router.ProvideGitHandler(config, provider, repoStore, authenticator, authorizer, gitrpcInterface)
|
||||
webHandler := router2.ProvideWebHandler(config)
|
||||
routerRouter := router2.ProvideRouter(config, apiHandler, gitHandler, webHandler)
|
||||
|
@ -14,6 +14,7 @@ import (
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
gitrpcserver "github.com/harness/gitness/gitrpc/server"
|
||||
gitrpccron "github.com/harness/gitness/gitrpc/server/cron"
|
||||
checkcontroller "github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/controller/githook"
|
||||
"github.com/harness/gitness/internal/api/controller/principal"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
@ -85,6 +86,7 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
||||
pubsub.WireSet,
|
||||
codecomments.WireSet,
|
||||
gitrpccron.WireSet,
|
||||
checkcontroller.WireSet,
|
||||
)
|
||||
return &system{}, nil
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import (
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
server2 "github.com/harness/gitness/gitrpc/server"
|
||||
"github.com/harness/gitness/gitrpc/server/cron"
|
||||
check2 "github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/controller/githook"
|
||||
"github.com/harness/gitness/internal/api/controller/principal"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
@ -130,7 +131,9 @@ func initSystem(ctx context.Context, config *types.Config) (*system, error) {
|
||||
githookController := githook.ProvideController(db, authorizer, principalStore, repoStore, eventsReporter)
|
||||
serviceaccountController := serviceaccount.NewController(principalUID, authorizer, principalStore, spaceStore, repoStore, tokenStore)
|
||||
principalController := principal.NewController(principalStore)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, repoController, spaceController, pullreqController, webhookController, githookController, serviceaccountController, controller, principalController)
|
||||
checkStore := database.ProvideCheckStore(db, principalInfoCache)
|
||||
checkController := check2.ProvideController(db, authorizer, checkStore, repoStore, gitrpcInterface)
|
||||
apiHandler := router.ProvideAPIHandler(config, authenticator, repoController, spaceController, pullreqController, webhookController, githookController, serviceaccountController, controller, principalController, checkController)
|
||||
gitHandler := router.ProvideGitHandler(config, provider, repoStore, authenticator, authorizer, gitrpcInterface)
|
||||
webHandler := router.ProvideWebHandler(config)
|
||||
routerRouter := router.ProvideRouter(config, apiHandler, gitHandler, webHandler)
|
||||
|
17
gitrpc/validate.go
Normal file
17
gitrpc/validate.go
Normal file
@ -0,0 +1,17 @@
|
||||
// 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 gitrpc
|
||||
|
||||
import "regexp"
|
||||
|
||||
var matchCommitSHA = regexp.MustCompile("^[0-9a-f]+$")
|
||||
|
||||
func ValidateCommitSHA(commitSHA string) bool {
|
||||
if len(commitSHA) != 40 && len(commitSHA) != 64 {
|
||||
return false
|
||||
}
|
||||
|
||||
return matchCommitSHA.MatchString(commitSHA)
|
||||
}
|
34
internal/api/controller/check/check_list.go
Normal file
34
internal/api/controller/check/check_list.go
Normal file
@ -0,0 +1,34 @@
|
||||
// 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 check
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/internal/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// ListChecks return an array of status check results for a commit in a repository.
|
||||
func (c *Controller) ListChecks(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
commitSHA string,
|
||||
) ([]*types.Check, 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)
|
||||
}
|
||||
|
||||
list, err := c.checkStore.List(ctx, repo.ID, commitSHA)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list status check results for repo=%s: %w", repo.UID, err)
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
122
internal/api/controller/check/check_report.go
Normal file
122
internal/api/controller/check/check_report.go
Normal file
@ -0,0 +1,122 @@
|
||||
// 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 check
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/internal/api/usererror"
|
||||
"github.com/harness/gitness/internal/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
type ReportInput struct {
|
||||
CheckUID string `json:"check_uid"`
|
||||
Status enum.CheckStatus `json:"status"`
|
||||
Summary string `json:"summary"`
|
||||
Link string `json:"link"`
|
||||
Payload types.CheckPayload `json:"payload"`
|
||||
}
|
||||
|
||||
var regexpCheckUID = "^[a-zA-Z_][0-9a-zA-Z-_.$]{0,127}$"
|
||||
var matcherCheckUID = regexp.MustCompile(regexpCheckUID)
|
||||
|
||||
// Validate validates and sanitizes the ReportInput data.
|
||||
func (in *ReportInput) Validate() error {
|
||||
if in.CheckUID == "" {
|
||||
return usererror.BadRequest("Status check UID is missing")
|
||||
}
|
||||
|
||||
if !matcherCheckUID.MatchString(in.CheckUID) {
|
||||
return usererror.BadRequestf("Status check UID must match the regular expression: %s", regexpCheckUID)
|
||||
}
|
||||
|
||||
_, ok := in.Status.Sanitize()
|
||||
if !ok {
|
||||
return usererror.BadRequest("Invalid value provided for status check status")
|
||||
}
|
||||
|
||||
payloadKind, ok := in.Payload.Kind.Sanitize()
|
||||
if !ok {
|
||||
return usererror.BadRequest("Invalid value provided for the payload type")
|
||||
}
|
||||
in.Payload.Kind = payloadKind
|
||||
|
||||
switch in.Payload.Kind {
|
||||
case enum.CheckPayloadKindExternal:
|
||||
// the default external type does not support payload: clear it here
|
||||
in.Payload.Version = ""
|
||||
in.Payload.Data = []byte{'{', '}'}
|
||||
|
||||
if in.Link == "" { // the link is mandatory for the external
|
||||
return usererror.BadRequest("Link is missing")
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Report modifies an existing or creates a new (if none yet exists) status check report for a specific commit.
|
||||
func (c *Controller) Report(
|
||||
ctx context.Context,
|
||||
session *auth.Session,
|
||||
repoRef string,
|
||||
commitSHA string,
|
||||
in *ReportInput,
|
||||
metadata map[string]string,
|
||||
) (*types.Check, error) {
|
||||
repo, err := c.getRepoCheckAccess(ctx, session, repoRef, enum.PermissionCommitCheckReport)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to acquire access access to repo: %w", err)
|
||||
}
|
||||
|
||||
if errValidate := in.Validate(); errValidate != nil {
|
||||
return nil, errValidate
|
||||
}
|
||||
|
||||
if !gitrpc.ValidateCommitSHA(commitSHA) {
|
||||
return nil, usererror.BadRequest("invalid commit SHA provided")
|
||||
}
|
||||
|
||||
_, err = c.gitRPCClient.GetCommit(ctx, &gitrpc.GetCommitParams{
|
||||
ReadParams: gitrpc.ReadParams{RepoUID: repo.GitUID},
|
||||
SHA: commitSHA,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to commit sha=%s: %w", commitSHA, err)
|
||||
}
|
||||
|
||||
now := time.Now().UnixMilli()
|
||||
|
||||
metadataJson, _ := json.Marshal(metadata)
|
||||
|
||||
statusCheckReport := &types.Check{
|
||||
CreatedBy: session.Principal.ID,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
RepoID: repo.ID,
|
||||
CommitSHA: commitSHA,
|
||||
UID: in.CheckUID,
|
||||
Status: in.Status,
|
||||
Summary: in.Summary,
|
||||
Link: in.Link,
|
||||
Payload: in.Payload,
|
||||
Metadata: metadataJson,
|
||||
ReportedBy: *session.Principal.ToPrincipalInfo(),
|
||||
}
|
||||
|
||||
err = c.checkStore.Upsert(ctx, statusCheckReport)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to upsert status check result for repo=%s: %w", repo.UID, err)
|
||||
}
|
||||
|
||||
return statusCheckReport, nil
|
||||
}
|
65
internal/api/controller/check/controller.go
Normal file
65
internal/api/controller/check/controller.go
Normal file
@ -0,0 +1,65 @@
|
||||
// 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 check
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
apiauth "github.com/harness/gitness/internal/api/auth"
|
||||
"github.com/harness/gitness/internal/api/usererror"
|
||||
"github.com/harness/gitness/internal/auth"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
type Controller struct {
|
||||
db *sqlx.DB
|
||||
authorizer authz.Authorizer
|
||||
checkStore store.CheckStore
|
||||
reqCheckStore store.ReqCheckStore
|
||||
repoStore store.RepoStore
|
||||
gitRPCClient gitrpc.Interface
|
||||
}
|
||||
|
||||
func NewController(
|
||||
db *sqlx.DB,
|
||||
authorizer authz.Authorizer,
|
||||
checkStore store.CheckStore,
|
||||
repoStore store.RepoStore,
|
||||
gitRPCClient gitrpc.Interface,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
db: db,
|
||||
authorizer: authorizer,
|
||||
checkStore: checkStore,
|
||||
repoStore: repoStore,
|
||||
gitRPCClient: gitRPCClient,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) getRepoCheckAccess(ctx context.Context,
|
||||
session *auth.Session, repoRef string, reqPermission enum.Permission,
|
||||
) (*types.Repository, error) {
|
||||
if repoRef == "" {
|
||||
return nil, usererror.BadRequest("A valid repository reference must be provided.")
|
||||
}
|
||||
|
||||
repo, err := c.repoStore.FindByRef(ctx, repoRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find repository: %w", err)
|
||||
}
|
||||
|
||||
if err = apiauth.CheckRepo(ctx, c.authorizer, session, repo, reqPermission, false); err != nil {
|
||||
return nil, fmt.Errorf("access check failed: %w", err)
|
||||
}
|
||||
|
||||
return repo, nil
|
||||
}
|
30
internal/api/controller/check/wire.go
Normal file
30
internal/api/controller/check/wire.go
Normal file
@ -0,0 +1,30 @@
|
||||
// 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 check
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/internal/auth/authz"
|
||||
"github.com/harness/gitness/internal/store"
|
||||
|
||||
"github.com/google/wire"
|
||||
"github.com/jmoiron/sqlx"
|
||||
)
|
||||
|
||||
// WireSet provides a wire set for this package.
|
||||
var WireSet = wire.NewSet(
|
||||
ProvideController,
|
||||
)
|
||||
|
||||
func ProvideController(db *sqlx.DB, authorizer authz.Authorizer,
|
||||
checkStore store.CheckStore,
|
||||
repoStore store.RepoStore,
|
||||
rpcClient gitrpc.Interface,
|
||||
) *Controller {
|
||||
return NewController(db, authorizer,
|
||||
checkStore,
|
||||
repoStore,
|
||||
rpcClient)
|
||||
}
|
41
internal/api/handler/check/check_list.go
Normal file
41
internal/api/handler/check/check_list.go
Normal file
@ -0,0 +1,41 @@
|
||||
// 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 pullreq
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/render"
|
||||
"github.com/harness/gitness/internal/api/request"
|
||||
)
|
||||
|
||||
// HandleCheckList is an HTTP handler for listing status check results for a repository.
|
||||
func HandleCheckList(checkCtrl *check.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
commitSHA, err := request.GetCommitSHAFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
list, err := checkCtrl.ListChecks(ctx, session, repoRef, commitSHA)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, list)
|
||||
}
|
||||
}
|
50
internal/api/handler/check/check_report.go
Normal file
50
internal/api/handler/check/check_report.go
Normal file
@ -0,0 +1,50 @@
|
||||
// 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 pullreq
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/render"
|
||||
"github.com/harness/gitness/internal/api/request"
|
||||
)
|
||||
|
||||
// HandleCheckReport is an HTTP handler for reporting status check results.
|
||||
func HandleCheckReport(checkCtrl *check.Controller) http.HandlerFunc {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
repoRef, err := request.GetRepoRefFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
commitSHA, err := request.GetCommitSHAFromPath(r)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
in := new(check.ReportInput)
|
||||
err = json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
statusCheck, err := checkCtrl.Report(ctx, session,
|
||||
repoRef, commitSHA, in, map[string]string{})
|
||||
if err != nil {
|
||||
render.TranslatedUserError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
render.JSON(w, http.StatusOK, statusCheck)
|
||||
}
|
||||
}
|
54
internal/api/openapi/check.go
Normal file
54
internal/api/openapi/check.go
Normal file
@ -0,0 +1,54 @@
|
||||
// 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 openapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/usererror"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"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.SetJSONResponse(&reportStatusCheckResults, new(types.Check), http.StatusOK)
|
||||
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(usererror.Error), http.StatusBadRequest)
|
||||
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(usererror.Error), http.StatusInternalServerError)
|
||||
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&reportStatusCheckResults, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodPut, "/repos/{repo_ref}/checks/commits/{commit_sha}",
|
||||
reportStatusCheckResults)
|
||||
|
||||
listStatusCheckResults := openapi3.Operation{}
|
||||
listStatusCheckResults.WithTags(tag)
|
||||
listStatusCheckResults.WithMapOfAnything(map[string]interface{}{"operationId": "listStatusCheckResults"})
|
||||
_ = reflector.SetRequest(&listStatusCheckResults, new(listStatusCheckResultsRequest), 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)
|
||||
_ = reflector.SetJSONResponse(&listStatusCheckResults, new(usererror.Error), http.StatusUnauthorized)
|
||||
_ = reflector.SetJSONResponse(&listStatusCheckResults, new(usererror.Error), http.StatusForbidden)
|
||||
_ = reflector.Spec.AddOperation(http.MethodGet, "/repos/{repo_ref}/checks/commits/{commit_sha}",
|
||||
listStatusCheckResults)
|
||||
}
|
@ -43,6 +43,7 @@ func Generate() *openapi3.Spec {
|
||||
resourceOperations(&reflector)
|
||||
pullReqOperations(&reflector)
|
||||
webhookOperations(&reflector)
|
||||
checkOperations(&reflector)
|
||||
|
||||
//
|
||||
// define security scheme
|
||||
|
@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/controller/githook"
|
||||
"github.com/harness/gitness/internal/api/controller/principal"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
@ -17,6 +18,7 @@ import (
|
||||
"github.com/harness/gitness/internal/api/controller/user"
|
||||
"github.com/harness/gitness/internal/api/controller/webhook"
|
||||
"github.com/harness/gitness/internal/api/handler/account"
|
||||
handlercheck "github.com/harness/gitness/internal/api/handler/check"
|
||||
handlergithook "github.com/harness/gitness/internal/api/handler/githook"
|
||||
handlerprincipal "github.com/harness/gitness/internal/api/handler/principal"
|
||||
handlerpullreq "github.com/harness/gitness/internal/api/handler/pullreq"
|
||||
@ -64,7 +66,9 @@ func NewAPIHandler(
|
||||
githookCtrl *githook.Controller,
|
||||
saCtrl *serviceaccount.Controller,
|
||||
userCtrl *user.Controller,
|
||||
principalCtrl *principal.Controller) APIHandler {
|
||||
principalCtrl *principal.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
) APIHandler {
|
||||
// Use go-chi router for inner routing.
|
||||
r := chi.NewRouter()
|
||||
|
||||
@ -85,7 +89,8 @@ func NewAPIHandler(
|
||||
r.Use(middlewareauthn.Attempt(authenticator, authn.SourceRouterAPI))
|
||||
|
||||
r.Route("/v1", func(r chi.Router) {
|
||||
setupRoutesV1(r, repoCtrl, spaceCtrl, pullreqCtrl, webhookCtrl, githookCtrl, saCtrl, userCtrl, principalCtrl)
|
||||
setupRoutesV1(r, repoCtrl, spaceCtrl, pullreqCtrl, webhookCtrl, githookCtrl,
|
||||
saCtrl, userCtrl, principalCtrl, checkCtrl)
|
||||
})
|
||||
|
||||
// wrap router in terminatedPath encoder.
|
||||
@ -106,11 +111,18 @@ func corsHandler(config *types.Config) func(http.Handler) http.Handler {
|
||||
}
|
||||
|
||||
func setupRoutesV1(r chi.Router,
|
||||
repoCtrl *repo.Controller, spaceCtrl *space.Controller,
|
||||
pullreqCtrl *pullreq.Controller, webhookCtrl *webhook.Controller, githookCtrl *githook.Controller,
|
||||
saCtrl *serviceaccount.Controller, userCtrl *user.Controller, principalCtrl *principal.Controller) {
|
||||
repoCtrl *repo.Controller,
|
||||
spaceCtrl *space.Controller,
|
||||
pullreqCtrl *pullreq.Controller,
|
||||
webhookCtrl *webhook.Controller,
|
||||
githookCtrl *githook.Controller,
|
||||
saCtrl *serviceaccount.Controller,
|
||||
userCtrl *user.Controller,
|
||||
principalCtrl *principal.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
) {
|
||||
setupSpaces(r, spaceCtrl, repoCtrl)
|
||||
setupRepos(r, repoCtrl, pullreqCtrl, webhookCtrl)
|
||||
setupRepos(r, repoCtrl, pullreqCtrl, webhookCtrl, checkCtrl)
|
||||
setupUser(r, userCtrl)
|
||||
setupServiceAccounts(r, saCtrl)
|
||||
setupPrincipals(r, principalCtrl)
|
||||
@ -151,8 +163,12 @@ func setupSpaces(r chi.Router, spaceCtrl *space.Controller, repoCtrl *repo.Contr
|
||||
})
|
||||
}
|
||||
|
||||
func setupRepos(r chi.Router, repoCtrl *repo.Controller, pullreqCtrl *pullreq.Controller,
|
||||
webhookCtrl *webhook.Controller) {
|
||||
func setupRepos(r chi.Router,
|
||||
repoCtrl *repo.Controller,
|
||||
pullreqCtrl *pullreq.Controller,
|
||||
webhookCtrl *webhook.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
) {
|
||||
r.Route("/repos", func(r chi.Router) {
|
||||
// Create takes path and parentId via body, not uri
|
||||
r.Post("/", handlerrepo.HandleCreate(repoCtrl))
|
||||
@ -239,6 +255,8 @@ func setupRepos(r chi.Router, repoCtrl *repo.Controller, pullreqCtrl *pullreq.Co
|
||||
SetupPullReq(r, pullreqCtrl)
|
||||
|
||||
SetupWebhook(r, webhookCtrl)
|
||||
|
||||
SetupChecks(r, checkCtrl)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -312,6 +330,15 @@ func SetupWebhook(r chi.Router, webhookCtrl *webhook.Controller) {
|
||||
})
|
||||
}
|
||||
|
||||
func SetupChecks(r chi.Router, checkCtrl *check.Controller) {
|
||||
r.Route("/checks", func(r chi.Router) {
|
||||
r.Route(fmt.Sprintf("/commits/{%s}", request.PathParamCommitSHA), func(r chi.Router) {
|
||||
r.Put("/", handlercheck.HandleCheckReport(checkCtrl))
|
||||
r.Get("/", handlercheck.HandleCheckList(checkCtrl))
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func setupUser(r chi.Router, userCtrl *user.Controller) {
|
||||
r.Route("/user", func(r chi.Router) {
|
||||
// enforce principal authenticated and it's a user
|
||||
|
@ -6,6 +6,7 @@ package router
|
||||
|
||||
import (
|
||||
"github.com/harness/gitness/gitrpc"
|
||||
"github.com/harness/gitness/internal/api/controller/check"
|
||||
"github.com/harness/gitness/internal/api/controller/githook"
|
||||
"github.com/harness/gitness/internal/api/controller/principal"
|
||||
"github.com/harness/gitness/internal/api/controller/pullreq"
|
||||
@ -62,9 +63,11 @@ func ProvideAPIHandler(
|
||||
githookCtrl *githook.Controller,
|
||||
saCtrl *serviceaccount.Controller,
|
||||
userCtrl *user.Controller,
|
||||
principalCtrl *principal.Controller) APIHandler {
|
||||
principalCtrl *principal.Controller,
|
||||
checkCtrl *check.Controller,
|
||||
) APIHandler {
|
||||
return NewAPIHandler(config, authenticator, repoCtrl, spaceCtrl, pullreqCtrl,
|
||||
webhookCtrl, githookCtrl, saCtrl, userCtrl, principalCtrl)
|
||||
webhookCtrl, githookCtrl, saCtrl, userCtrl, principalCtrl, checkCtrl)
|
||||
}
|
||||
|
||||
func ProvideWebHandler(config *types.Config) WebHandler {
|
||||
|
@ -46,29 +46,31 @@ const (
|
||||
,check_updated
|
||||
,check_repo_id
|
||||
,check_commit_sha
|
||||
,check_type
|
||||
,check_uid
|
||||
,check_status
|
||||
,check_summary
|
||||
,check_link
|
||||
,check_payload
|
||||
,check_metadata`
|
||||
,check_metadata
|
||||
,check_payload_kind
|
||||
,check_payload_version`
|
||||
)
|
||||
|
||||
type check struct {
|
||||
ID int64 `db:"check_id"`
|
||||
CreatedBy int64 `db:"check_created_by"`
|
||||
Created int64 `db:"check_created"`
|
||||
Updated int64 `db:"check_updated"`
|
||||
RepoID int64 `db:"check_repo_id"`
|
||||
CommitSHA string `db:"check_commit_sha"`
|
||||
Type string `db:"check_type"`
|
||||
UID string `db:"check_uid"`
|
||||
Status enum.CheckStatus `db:"check_status"`
|
||||
Summary string `db:"check_summary"`
|
||||
Link string `db:"check_link"`
|
||||
Payload json.RawMessage `db:"check_payload"`
|
||||
Metadata json.RawMessage `db:"check_metadata"`
|
||||
ID int64 `db:"check_id"`
|
||||
CreatedBy int64 `db:"check_created_by"`
|
||||
Created int64 `db:"check_created"`
|
||||
Updated int64 `db:"check_updated"`
|
||||
RepoID int64 `db:"check_repo_id"`
|
||||
CommitSHA string `db:"check_commit_sha"`
|
||||
UID string `db:"check_uid"`
|
||||
Status enum.CheckStatus `db:"check_status"`
|
||||
Summary string `db:"check_summary"`
|
||||
Link string `db:"check_link"`
|
||||
Payload json.RawMessage `db:"check_payload"`
|
||||
Metadata json.RawMessage `db:"check_metadata"`
|
||||
PayloadKind enum.CheckPayloadKind `db:"check_payload_kind"`
|
||||
PayloadVersion string `db:"check_payload_version"`
|
||||
}
|
||||
|
||||
// Upsert creates new or updates an existing status check result.
|
||||
@ -80,26 +82,28 @@ func (s *CheckStore) Upsert(ctx context.Context, check *types.Check) error {
|
||||
,check_updated
|
||||
,check_repo_id
|
||||
,check_commit_sha
|
||||
,check_type
|
||||
,check_uid
|
||||
,check_status
|
||||
,check_summary
|
||||
,check_link
|
||||
,check_payload
|
||||
,check_metadata
|
||||
,check_payload_kind
|
||||
,check_payload_version
|
||||
) VALUES (
|
||||
:check_created_by
|
||||
,:check_created
|
||||
,:check_updated
|
||||
,:check_repo_id
|
||||
,:check_commit_sha
|
||||
,:check_type
|
||||
,:check_uid
|
||||
,:check_status
|
||||
,:check_summary
|
||||
,:check_link
|
||||
,:check_payload
|
||||
,:check_metadata
|
||||
,:check_payload_kind
|
||||
,:check_payload_version
|
||||
)
|
||||
ON CONFLICT (check_repo_id, check_commit_sha, check_uid) DO
|
||||
UPDATE SET
|
||||
@ -109,7 +113,9 @@ func (s *CheckStore) Upsert(ctx context.Context, check *types.Check) error {
|
||||
,check_link = :check_link
|
||||
,check_payload = :check_payload
|
||||
,check_metadata = :check_metadata
|
||||
RETURNING check_id`
|
||||
,check_payload_kind = :check_payload_kind
|
||||
,check_payload_version = :check_payload_version
|
||||
RETURNING check_id, check_created_by, check_created`
|
||||
|
||||
db := dbtx.GetAccessor(ctx, s.db)
|
||||
|
||||
@ -118,7 +124,7 @@ func (s *CheckStore) Upsert(ctx context.Context, check *types.Check) error {
|
||||
return processSQLErrorf(err, "Failed to bind status check object")
|
||||
}
|
||||
|
||||
if err = db.QueryRowContext(ctx, query, arg...).Scan(&check.ID); err != nil {
|
||||
if err = db.QueryRowContext(ctx, query, arg...).Scan(&check.ID, &check.CreatedBy, &check.Created); err != nil {
|
||||
return processSQLErrorf(err, "Upsert query failed")
|
||||
}
|
||||
|
||||
@ -182,19 +188,20 @@ func (s *CheckStore) ListRecent(ctx context.Context, repoID int64, since time.Ti
|
||||
|
||||
func mapInternalCheck(c *types.Check) *check {
|
||||
m := &check{
|
||||
ID: c.ID,
|
||||
CreatedBy: c.CreatedBy,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
RepoID: c.RepoID,
|
||||
CommitSHA: c.CommitSHA,
|
||||
Type: c.Type,
|
||||
UID: c.UID,
|
||||
Status: c.Status,
|
||||
Summary: c.Summary,
|
||||
Link: c.Link,
|
||||
Payload: c.Payload,
|
||||
Metadata: c.Metadata,
|
||||
ID: c.ID,
|
||||
CreatedBy: c.CreatedBy,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
RepoID: c.RepoID,
|
||||
CommitSHA: c.CommitSHA,
|
||||
UID: c.UID,
|
||||
Status: c.Status,
|
||||
Summary: c.Summary,
|
||||
Link: c.Link,
|
||||
Payload: c.Payload.Data,
|
||||
Metadata: c.Metadata,
|
||||
PayloadKind: c.Payload.Kind,
|
||||
PayloadVersion: c.Payload.Version,
|
||||
}
|
||||
|
||||
return m
|
||||
@ -202,19 +209,22 @@ func mapInternalCheck(c *types.Check) *check {
|
||||
|
||||
func mapCheck(c *check) *types.Check {
|
||||
return &types.Check{
|
||||
ID: c.ID,
|
||||
CreatedBy: c.CreatedBy,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
RepoID: c.RepoID,
|
||||
CommitSHA: c.CommitSHA,
|
||||
Type: c.Type,
|
||||
UID: c.UID,
|
||||
Status: c.Status,
|
||||
Summary: c.Summary,
|
||||
Link: c.Link,
|
||||
Payload: c.Payload,
|
||||
Metadata: c.Metadata,
|
||||
ID: c.ID,
|
||||
CreatedBy: c.CreatedBy,
|
||||
Created: c.Created,
|
||||
Updated: c.Updated,
|
||||
RepoID: c.RepoID,
|
||||
CommitSHA: c.CommitSHA,
|
||||
UID: c.UID,
|
||||
Status: c.Status,
|
||||
Summary: c.Summary,
|
||||
Link: c.Link,
|
||||
Metadata: c.Metadata,
|
||||
Payload: types.CheckPayload{
|
||||
Version: c.PayloadVersion,
|
||||
Kind: c.PayloadKind,
|
||||
Data: c.Payload,
|
||||
},
|
||||
ReportedBy: types.PrincipalInfo{},
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,4 @@
|
||||
ALTER TABLE checks
|
||||
ADD COLUMN check_type TEXT NOT NULL DEFAULT '',
|
||||
DROP COLUMN check_payload_version,
|
||||
DROP COLUMN check_payload_kind;
|
@ -0,0 +1,4 @@
|
||||
ALTER TABLE checks
|
||||
ADD COLUMN check_payload_version TEXT NOT NULL DEFAULT '',
|
||||
ADD COLUMN check_payload_kind TEXT NOT NULL DEFAULT '',
|
||||
DROP COLUMN check_type;
|
@ -0,0 +1,3 @@
|
||||
ALTER TABLE checks ADD COLUMN check_type TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE checks DROP COLUMN check_payload_version;
|
||||
ALTER TABLE checks DROP COLUMN check_payload_kind;
|
@ -0,0 +1,3 @@
|
||||
ALTER TABLE checks ADD COLUMN check_payload_version TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE checks ADD COLUMN check_payload_kind TEXT NOT NULL DEFAULT '';
|
||||
ALTER TABLE checks DROP COLUMN check_type;
|
@ -17,17 +17,22 @@ type Check struct {
|
||||
Updated int64 `json:"updated"`
|
||||
RepoID int64 `json:"-"` // status checks are always returned for a commit in a repository
|
||||
CommitSHA string `json:"-"` // status checks are always returned for a commit in a repository
|
||||
Type string `json:"type"`
|
||||
UID string `json:"uid"`
|
||||
Status enum.CheckStatus `json:"status"`
|
||||
Summary string `json:"summary"`
|
||||
Link string `json:"link"`
|
||||
Payload json.RawMessage `json:"payload"`
|
||||
Metadata json.RawMessage `json:"metadata"`
|
||||
|
||||
Payload CheckPayload `json:"payload"`
|
||||
ReportedBy PrincipalInfo `json:"reported_by"`
|
||||
}
|
||||
|
||||
type CheckPayload struct {
|
||||
Version string `json:"version"`
|
||||
Kind enum.CheckPayloadKind `json:"kind"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
type ReqCheck struct {
|
||||
ID int64 `json:"id"`
|
||||
CreatedBy int64 `json:"-"` // clients will use "added_by"
|
||||
|
@ -11,7 +11,7 @@ func (CheckStatus) Enum() []interface{} { return toInterfaceSlic
|
||||
func (s CheckStatus) Sanitize() (CheckStatus, bool) { return Sanitize(s, GetAllCheckStatuses) }
|
||||
func GetAllCheckStatuses() ([]CheckStatus, CheckStatus) { return checkStatuses, "" }
|
||||
|
||||
// PullReqState enumeration.
|
||||
// CheckStatus enumeration.
|
||||
const (
|
||||
CheckStatusPending CheckStatus = "pending"
|
||||
CheckStatusRunning CheckStatus = "running"
|
||||
@ -27,3 +27,23 @@ var checkStatuses = sortEnum([]CheckStatus{
|
||||
CheckStatusFailure,
|
||||
CheckStatusError,
|
||||
})
|
||||
|
||||
// CheckPayloadKind defines status payload type.
|
||||
type CheckPayloadKind string
|
||||
|
||||
func (CheckPayloadKind) Enum() []interface{} { return toInterfaceSlice(checkPayloadTypes) }
|
||||
func (s CheckPayloadKind) Sanitize() (CheckPayloadKind, bool) {
|
||||
return Sanitize(s, GetAllCheckPayloadTypes)
|
||||
}
|
||||
func GetAllCheckPayloadTypes() ([]CheckPayloadKind, CheckPayloadKind) {
|
||||
return checkPayloadTypes, CheckPayloadKindExternal
|
||||
}
|
||||
|
||||
// CheckPayloadKind enumeration.
|
||||
const (
|
||||
CheckPayloadKindExternal CheckPayloadKind = "external"
|
||||
)
|
||||
|
||||
var checkPayloadTypes = sortEnum([]CheckPayloadKind{
|
||||
CheckPayloadKindExternal,
|
||||
})
|
||||
|
@ -70,3 +70,10 @@ const (
|
||||
PermissionServiceDelete Permission = "service_delete"
|
||||
PermissionServiceEditAdmin Permission = "service_editadmin"
|
||||
)
|
||||
|
||||
const (
|
||||
/*
|
||||
----- COMMIT CHECK -----
|
||||
*/
|
||||
PermissionCommitCheckReport Permission = "commitCheck_report"
|
||||
)
|
||||
|
Loading…
Reference in New Issue
Block a user