Skip to content

Commit

Permalink
chore: artifact api refactoring (#4137)
Browse files Browse the repository at this point in the history
* wip

* wip

* ci type parent artifats fetched

* commented not required data

* almost done, optimise TODOs

* pagination done for OSS

* calling V2 function in resthandler

* bug fix for no deployment triggered on the pipeline and query fix for emptyexclude artifacts ids

* query fix for emptyexclude artifacts ids

* code review comments

* searchstring refactor fix

* added rollback API V2 in

* added artifact createdOn time

* pagination fix

* fix

* delete redundant ids

* setting data source value

* sql script

* queries optimised and created queryBuilder for getting artifacts list

* sync oss code

* optimise getting  git-triggers logic

* fix

* totalcount fix

* offset validation

* enterprise sync

* offset issue

* query change

* query change

* fix

* fix

* parenthesis fix

* update script

* make like query part conditional

* make const of empty like regex

---------

Co-authored-by: Kripansh <kripansh@devtron.ai>
Co-authored-by: ShashwatDadhich <dadhichshashwat1808@gmail.com>
  • Loading branch information
3 people committed Nov 15, 2023
1 parent 09536a7 commit a67365f
Show file tree
Hide file tree
Showing 38 changed files with 7,835 additions and 42 deletions.
23 changes: 23 additions & 0 deletions api/bean/ValuesOverrideRequest.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,26 @@ type TriggerEvent struct {
TriggeredBy int32
TriggerdAt time.Time
}

type ArtifactsListFilterOptions struct {
//list filter data
Limit int
Offset int
SearchString string
Order string

//self stage data
PipelineId int
StageType WorkflowType

//parent satge data
ParentCdId int
ParentId int
ParentStageType WorkflowType

//excludeArtifactIds
ExcludeArtifactIds []int

//excludeWfRunners
ExcludeWfrIds []int
}
51 changes: 47 additions & 4 deletions api/restHandler/app/DeploymentPipelineRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1176,7 +1176,34 @@ func (handler PipelineConfigRestHandlerImpl) GetArtifactsByCDPipeline(w http.Res
}
stage := r.URL.Query().Get("stage")
if len(stage) == 0 {
stage = "PRE"
stage = pipeline.WorklowTypePre
}
searchString := ""
search := r.URL.Query().Get("search")
if len(search) != 0 {
searchString = search
}

offset := 0
limit := 10
offsetQueryParam := r.URL.Query().Get("offset")
if offsetQueryParam != "" {
offset, err = strconv.Atoi(offsetQueryParam)
if err != nil || offset < 0 {
handler.Logger.Errorw("request err, GetArtifactsForRollback", "err", err, "offsetQueryParam", offsetQueryParam)
common.WriteJsonResp(w, err, "invalid offset", http.StatusBadRequest)
return
}
}

sizeQueryParam := r.URL.Query().Get("size")
if sizeQueryParam != "" {
limit, err = strconv.Atoi(sizeQueryParam)
if err != nil {
handler.Logger.Errorw("request err, GetArtifactsForRollback", "err", err, "sizeQueryParam", sizeQueryParam)
common.WriteJsonResp(w, err, "invalid size", http.StatusBadRequest)
return
}
}
handler.Logger.Infow("request payload, GetArtifactsByCDPipeline", "cdPipelineId", cdPipelineId, "stage", stage)

Expand Down Expand Up @@ -1207,8 +1234,17 @@ func (handler PipelineConfigRestHandlerImpl) GetArtifactsByCDPipeline(w http.Res
return
}
//rbac block ends here

ciArtifactResponse, err := handler.pipelineBuilder.RetrieveArtifactsByCDPipeline(pipeline, bean2.WorkflowType(stage))
var ciArtifactResponse *bean.CiArtifactResponse
if handler.pipelineRestHandlerEnvConfig.UseArtifactListApiV2 {
artifactsListFilterOptions := &bean2.ArtifactsListFilterOptions{
Limit: limit,
Offset: offset,
SearchString: searchString,
}
ciArtifactResponse, err = handler.pipelineBuilder.RetrieveArtifactsByCDPipelineV2(pipeline, bean2.WorkflowType(stage), artifactsListFilterOptions)
} else {
ciArtifactResponse, err = handler.pipelineBuilder.RetrieveArtifactsByCDPipeline(pipeline, bean2.WorkflowType(stage))
}
if err != nil {
handler.Logger.Errorw("service err, GetArtifactsByCDPipeline", "err", err, "cdPipelineId", cdPipelineId, "stage", stage)
common.WriteJsonResp(w, err, nil, http.StatusInternalServerError)
Expand Down Expand Up @@ -1431,6 +1467,8 @@ func (handler PipelineConfigRestHandlerImpl) GetArtifactsForRollback(w http.Resp
common.WriteJsonResp(w, err, "invalid size", http.StatusBadRequest)
return
}
searchString := r.URL.Query().Get("search")

//rbac block starts from here
object := handler.enforcerUtil.GetAppRBACName(app.AppName)
if ok := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionGet, object); !ok {
Expand All @@ -1444,9 +1482,14 @@ func (handler PipelineConfigRestHandlerImpl) GetArtifactsForRollback(w http.Resp
}
//rbac block ends here
//rbac for edit tags access
var ciArtifactResponse bean.CiArtifactResponse
triggerAccess := handler.enforcer.Enforce(token, casbin.ResourceApplications, casbin.ActionTrigger, object)
if handler.pipelineRestHandlerEnvConfig.UseArtifactListApiV2 {
ciArtifactResponse, err = handler.pipelineBuilder.FetchArtifactForRollbackV2(cdPipelineId, app.Id, offset, limit, searchString, app, deploymentPipeline)
} else {
ciArtifactResponse, err = handler.pipelineBuilder.FetchArtifactForRollback(cdPipelineId, app.Id, offset, limit, searchString)
}

ciArtifactResponse, err := handler.pipelineBuilder.FetchArtifactForRollback(cdPipelineId, app.Id, offset, limit)
if err != nil {
handler.Logger.Errorw("service err, GetArtifactsForRollback", "err", err, "cdPipelineId", cdPipelineId)
common.WriteJsonResp(w, err, "unable to fetch artifacts", http.StatusInternalServerError)
Expand Down
12 changes: 12 additions & 0 deletions api/restHandler/app/PipelineConfigRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"context"
"encoding/json"
"fmt"
"github.com/caarlos0/env"
"github.com/devtron-labs/devtron/api/restHandler/common"
"github.com/devtron-labs/devtron/client/gitSensor"
"github.com/devtron-labs/devtron/internal/sql/repository/helper"
Expand Down Expand Up @@ -62,6 +63,10 @@ import (
"gopkg.in/go-playground/validator.v9"
)

type PipelineRestHandlerEnvConfig struct {
UseArtifactListApiV2 bool `env:"USE_ARTIFACT_LISTING_API_V2"`
}

type DevtronAppRestHandler interface {
CreateApp(w http.ResponseWriter, r *http.Request)
DeleteApp(w http.ResponseWriter, r *http.Request)
Expand Down Expand Up @@ -124,6 +129,7 @@ type PipelineConfigRestHandlerImpl struct {
argoUserService argo.ArgoUserService
imageTaggingService pipeline.ImageTaggingService
deploymentTemplateService generateManifest.DeploymentTemplateService
pipelineRestHandlerEnvConfig *PipelineRestHandlerEnvConfig
}

func NewPipelineRestHandlerImpl(pipelineBuilder pipeline.PipelineBuilder, Logger *zap.SugaredLogger,
Expand All @@ -148,6 +154,11 @@ func NewPipelineRestHandlerImpl(pipelineBuilder pipeline.PipelineBuilder, Logger
scanResultRepository security.ImageScanResultRepository, gitProviderRepo repository.GitProviderRepository,
argoUserService argo.ArgoUserService, ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository,
imageTaggingService pipeline.ImageTaggingService) *PipelineConfigRestHandlerImpl {
envConfig := &PipelineRestHandlerEnvConfig{}
err := env.Parse(envConfig)
if err != nil {
Logger.Errorw("error in parsing PipelineRestHandlerEnvConfig", "err", err)
}
return &PipelineConfigRestHandlerImpl{
pipelineBuilder: pipelineBuilder,
Logger: Logger,
Expand Down Expand Up @@ -178,6 +189,7 @@ func NewPipelineRestHandlerImpl(pipelineBuilder pipeline.PipelineBuilder, Logger
ciPipelineMaterialRepository: ciPipelineMaterialRepository,
imageTaggingService: imageTaggingService,
deploymentTemplateService: deploymentTemplateService,
pipelineRestHandlerEnvConfig: envConfig,
}
}

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,7 @@ require (
github.com/prometheus/procfs v0.8.0 // indirect
github.com/robfig/cron v1.2.0 // indirect
github.com/russross/blackfriday v1.5.2 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/sergi/go-diff v1.1.0 // indirect
github.com/shopspring/decimal v1.2.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1038,6 +1038,8 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
Expand Down
117 changes: 116 additions & 1 deletion internal/sql/repository/CiArtifactRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,15 @@ import (
"go.uber.org/zap"
)

type CiArtifactWithExtraData struct {
CiArtifact
PayloadSchema string
TotalCount int
TriggeredBy int32
StartedOn time.Time
CdWorkflowRunnerId int
}

type CiArtifact struct {
tableName struct{} `sql:"ci_artifact" pg:",discard_unknown_columns"`
Id int `sql:"id,pk"`
Expand Down Expand Up @@ -59,7 +68,7 @@ type CiArtifactRepository interface {
GetArtifactParentCiAndWorkflowDetailsByIds(ids []int) ([]*CiArtifact, error)
GetByWfId(wfId int) (artifact *CiArtifact, err error)
GetArtifactsByCDPipeline(cdPipelineId, limit int, parentId int, parentType bean.WorkflowType) ([]*CiArtifact, error)

GetArtifactsByCDPipelineV3(listingFilterOpts *bean.ArtifactsListFilterOptions) ([]*CiArtifact, int, error)
GetLatestArtifactTimeByCiPipelineIds(ciPipelineIds []int) ([]*CiArtifact, error)
GetLatestArtifactTimeByCiPipelineId(ciPipelineId int) (*CiArtifact, error)
GetArtifactsByCDPipelineV2(cdPipelineId int) ([]CiArtifact, error)
Expand All @@ -72,6 +81,8 @@ type CiArtifactRepository interface {
GetByIds(ids []int) ([]*CiArtifact, error)
GetArtifactByCdWorkflowId(cdWorkflowId int) (artifact *CiArtifact, err error)
GetArtifactsByParentCiWorkflowId(parentCiWorkflowId int) ([]string, error)
FetchArtifactsByCdPipelineIdV2(listingFilterOptions bean.ArtifactsListFilterOptions) ([]CiArtifactWithExtraData, int, error)
FindArtifactByListFilter(listingFilterOptions *bean.ArtifactsListFilterOptions) ([]CiArtifact, int, error)
}

type CiArtifactRepositoryImpl struct {
Expand Down Expand Up @@ -240,6 +251,68 @@ func (impl CiArtifactRepositoryImpl) GetArtifactsByCDPipeline(cdPipelineId, limi
return artifactsAll, err
}

func (impl CiArtifactRepositoryImpl) GetArtifactsByCDPipelineV3(listingFilterOpts *bean.ArtifactsListFilterOptions) ([]*CiArtifact, int, error) {

if listingFilterOpts.ParentStageType != bean.CI_WORKFLOW_TYPE && listingFilterOpts.ParentStageType != bean.WEBHOOK_WORKFLOW_TYPE {
return nil, 0, nil
}

artifactsResp := make([]*CiArtifactWithExtraData, 0, listingFilterOpts.Limit)
var artifacts []*CiArtifact
totalCount := 0
finalQuery := BuildQueryForParentTypeCIOrWebhook(*listingFilterOpts)
_, err := impl.dbConnection.Query(&artifactsResp, finalQuery)
if err != nil {
return nil, totalCount, err
}
artifacts = make([]*CiArtifact, len(artifactsResp))
for i, _ := range artifactsResp {
artifacts[i] = &artifactsResp[i].CiArtifact
totalCount = artifactsResp[i].TotalCount
}

if len(artifacts) == 0 {
return artifacts, totalCount, nil
}
artifacts, err = impl.setDeployedDataInArtifacts(artifacts)
return artifacts, totalCount, err
}

func (impl CiArtifactRepositoryImpl) setDeployedDataInArtifacts(artifacts []*CiArtifact) ([]*CiArtifact, error) {
//processing
artifactsMap := make(map[int]*CiArtifact)
artifactsIds := make([]int, 0, len(artifacts))
for _, artifact := range artifacts {
artifactsMap[artifact.Id] = artifact
artifactsIds = append(artifactsIds, artifact.Id)
}

//(this will fetch all the artifacts that were deployed on the given pipeline atleast once in new->old deployed order)
artifactsDeployed := make([]*CiArtifact, 0, len(artifactsIds))
query := " SELECT cia.id,pco.created_on AS created_on " +
" FROM ci_artifact cia" +
" INNER JOIN pipeline_config_override pco ON pco.ci_artifact_id=cia.id" +
" WHERE pco.pipeline_id = ? " +
" AND cia.id IN (?) " +
" ORDER BY pco.id desc;"

_, err := impl.dbConnection.Query(&artifactsDeployed, query, pg.In(artifactsIds))
if err != nil {
return artifacts, nil
}

//set deployed time and latest deployed artifact
for _, deployedArtifact := range artifactsDeployed {
artifactId := deployedArtifact.Id
if _, ok := artifactsMap[artifactId]; ok {
artifactsMap[artifactId].Deployed = true
artifactsMap[artifactId].DeployedTime = deployedArtifact.CreatedOn
}
}

return artifacts, nil
}

func (impl CiArtifactRepositoryImpl) GetLatestArtifactTimeByCiPipelineIds(ciPipelineIds []int) ([]*CiArtifact, error) {
artifacts := make([]*CiArtifact, 0)
query := "select cws.pipeline_id, cws.created_on from " +
Expand Down Expand Up @@ -582,3 +655,45 @@ func (impl CiArtifactRepositoryImpl) GetArtifactsByParentCiWorkflowId(parentCiWo
}
return artifacts, err
}

func (impl CiArtifactRepositoryImpl) FindArtifactByListFilter(listingFilterOptions *bean.ArtifactsListFilterOptions) ([]CiArtifact, int, error) {

var ciArtifactsResp []CiArtifactWithExtraData
var ciArtifacts []CiArtifact
totalCount := 0
finalQuery := BuildQueryForArtifactsForCdStage(*listingFilterOptions)
_, err := impl.dbConnection.Query(&ciArtifactsResp, finalQuery)
if err == pg.ErrNoRows || len(ciArtifactsResp) == 0 {
return ciArtifacts, totalCount, nil
}
artifactIds := make([]int, len(ciArtifactsResp))
for i, af := range ciArtifactsResp {
artifactIds[i] = af.Id
totalCount = af.TotalCount
}

err = impl.dbConnection.
Model(&ciArtifacts).
Where("id IN (?) ", pg.In(artifactIds)).
Select()

if err == pg.ErrNoRows {
return ciArtifacts, totalCount, nil
}
return ciArtifacts, totalCount, err
}

func (impl CiArtifactRepositoryImpl) FetchArtifactsByCdPipelineIdV2(listingFilterOptions bean.ArtifactsListFilterOptions) ([]CiArtifactWithExtraData, int, error) {
var wfrList []CiArtifactWithExtraData
totalCount := 0
finalQuery := BuildQueryForArtifactsForRollback(listingFilterOptions)
_, err := impl.dbConnection.Query(&wfrList, finalQuery)
if err != nil && err != pg.ErrNoRows {
impl.logger.Errorw("error in getting Wfrs and ci artifacts by pipelineId", "err", err, "pipelineId", listingFilterOptions.PipelineId)
return nil, totalCount, err
}
if len(wfrList) > 0 {
totalCount = wfrList[0].TotalCount
}
return wfrList, totalCount, nil
}
Loading

0 comments on commit a67365f

Please sign in to comment.