123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838 |
- package service
- import (
- "context"
- "fmt"
- "strings"
- "time"
- "go-common/app/admin/ep/saga/conf"
- "go-common/app/admin/ep/saga/model"
- "go-common/app/admin/ep/saga/service/utils"
- "go-common/app/admin/ep/saga/service/wechat"
- "go-common/library/cache/memcache"
- "go-common/library/log"
- "github.com/xanzy/go-gitlab"
- )
- const (
- _gitHTTP = "http://git.bilibili.co/"
- _gitSSH = "git@git-test.bilibili.co:"
- _gitSSHTail = ".git"
- _manualJob = "manual"
- _androidScheduleJob = "daily branch check"
- _iosScheduleJob = "daily:on-schedule"
- )
- // QueryTeamPipeline query pipeline info according to team.
- func (s *Service) QueryTeamPipeline(c context.Context, req *model.TeamDataRequest) (resp *model.PipelineDataResp, err error) {
- var (
- projectInfo []*model.ProjectInfo
- reqProject = &model.ProjectInfoRequest{}
- data []*model.PipelineDataTime
- queryDes string
- total int
- succNum int
- key string
- keyNotExist bool
- )
- if len(req.Department) <= 0 && len(req.Business) <= 0 {
- log.Warn("query department and business are empty!")
- return
- }
- //get pipeline info from mc
- key = "saga_admin_" + req.Department + "_" + req.Business + "_" + model.KeyTypeConst[3]
- if resp, err = s.dao.GetPipeline(c, key); err != nil {
- if err == memcache.ErrNotFound {
- keyNotExist = true
- } else {
- return
- }
- } else {
- return
- }
- log.Info("sync team pipeline start => type= %d, Department= %s, Business= %s", req.QueryType, req.Department, req.Business)
- //query team projects
- reqProject.Department = req.Department
- reqProject.Business = req.Business
- if _, projectInfo, err = s.dao.QueryProjectInfo(false, reqProject); err != nil {
- return
- }
- if len(projectInfo) <= 0 {
- log.Warn("Found no project!")
- return
- }
- if data, total, succNum, err = s.QueryTeamPipelineByTime(projectInfo, model.LastWeekPerDay); err != nil {
- return
- }
- successScale := succNum * 100 / total
- queryDes = req.Department + " " + req.Business + " " + "pipeline上一周每天数量"
- resp = &model.PipelineDataResp{
- Department: req.Department,
- Business: req.Business,
- QueryDes: queryDes,
- Total: total,
- SuccessNum: succNum,
- SuccessScale: successScale,
- Data: data,
- }
- //set pipeline info to mc
- if keyNotExist {
- if err = s.dao.SetPipeline(c, key, resp); err != nil {
- return
- }
- }
- log.Info("sync team pipeline end")
- return
- }
- // QueryTeamPipelineByTime ...
- func (s *Service) QueryTeamPipelineByTime(projectInfo []*model.ProjectInfo, queryType int) (resp []*model.PipelineDataTime, allNum, succNum int, err error) {
- var (
- layout = "2006-01-02"
- since time.Time
- until time.Time
- total int
- success int
- count int
- )
- if queryType == model.LastWeekPerDay {
- count = model.DayNumPerWeek
- } else {
- log.Warn("Query Type is not in range!")
- return
- }
- year, month, day := time.Now().Date()
- weekDay := (int)(time.Now().Weekday())
- today := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
- for i := 0; i < count; i++ {
- since = today.AddDate(0, 0, -weekDay-i)
- until = today.AddDate(0, 0, -weekDay-i+1)
- totalAll := 0
- successAll := 0
- //log.Info("== start query from: %v, to: %v", since, until)
- for _, project := range projectInfo {
- if total, success, err = s.QueryProjectPipeline(project.ProjectID, "success", since, until); err != nil {
- return
- }
- totalAll = totalAll + total
- successAll = successAll + success
- }
- perData := &model.PipelineDataTime{
- TotalItem: totalAll,
- SuccessItem: successAll,
- StartTime: since.Format(layout),
- EndTime: until.Format(layout),
- }
- resp = append(resp, perData)
- allNum = allNum + totalAll
- succNum = succNum + successAll
- }
- return
- }
- // QueryProjectPipeline query pipeline info according to project id.
- func (s *Service) QueryProjectPipeline(projectID int, state string, since, until time.Time) (totalNum, stateNum int, err error) {
- var (
- pipelineList gitlab.PipelineList
- pipeline *gitlab.Pipeline
- resp *gitlab.Response
- startQuery bool
- )
- if _, resp, err = s.gitlab.ListProjectPipelines(1, projectID, ""); err != nil {
- return
- }
- page := 1
- for page <= resp.TotalPages {
- if !startQuery {
- if pipelineList, _, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- return
- }
- if page == 1 && len(pipelineList) <= 0 {
- return
- }
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, pipelineList[0].ID); err != nil {
- return
- }
- if pipeline.CreatedAt.After(until) {
- page++
- continue
- } else {
- startQuery = true
- page--
- continue
- }
- }
- if pipelineList, _, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- return
- }
- for _, v := range pipelineList {
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, v.ID); err != nil {
- return
- }
- createTime := pipeline.CreatedAt
- //year, month, day := createTime.Date()
- //log.Info("index: %d createTime: %d, month: %d, day: %d", k, year, month, day)
- if createTime.After(since) && createTime.Before(until) {
- totalNum = totalNum + 1
- if pipeline.Status == state {
- stateNum = stateNum + 1
- }
- }
- if createTime.Before(since) {
- return
- }
- }
- page++
- }
- return
- }
- // QueryProjectPipelineNew ...
- func (s *Service) QueryProjectPipelineNew(c context.Context, req *model.PipelineDataReq) (resp *model.PipelineDataAvgResp, err error) {
- var (
- data []*model.PipelineDataAvg
- queryDes string
- total int
- totalStatus int
- avgDurationTime float64
- avgPendingTime float64
- avgRunningTime float64
- )
- log.Info("QuerySingleProjectData Type: %d", req.Type)
- switch req.Type {
- case model.LastYearPerMonth:
- queryDes = model.LastYearPerMonthNote
- case model.LastMonthPerDay:
- queryDes = model.LastMonthPerDayNote
- case model.LastYearPerDay:
- queryDes = model.LastYearPerDayNote
- default:
- log.Warn("QueryProjectCommit Type is not in range")
- return
- }
- queryDes = req.ProjectName + " pipeline " + req.State + " " + queryDes
- if data, total, totalStatus, avgDurationTime, avgPendingTime, avgRunningTime, err = s.QueryProjectByTimeNew(c, req, req.Type); err != nil {
- return
- }
- resp = &model.PipelineDataAvgResp{
- ProjectName: req.ProjectName,
- QueryDes: queryDes,
- Status: req.State,
- Total: total,
- TotalStatus: totalStatus,
- AvgDurationTime: avgDurationTime,
- AvgPendingTime: avgPendingTime,
- AvgRunningTime: avgRunningTime,
- Data: data,
- }
- return
- }
- // QueryProjectByTimeNew ...
- func (s *Service) QueryProjectByTimeNew(c context.Context, req *model.PipelineDataReq, queryType int) (resp []*model.PipelineDataAvg, allNum, allStatusNum int, avgDurationTime, avgPendingTime, avgRunningTime float64, err error) {
- var (
- layout = "2006-01-02"
- since time.Time
- until time.Time
- count int
- pendingTimeListAll []float64
- runningTimeListAll []float64
- durationTimeListAll []float64
- pipelineTime *model.PipelineTime
- perData *model.PipelineDataAvg
- avgTotalTime float64
- totalNum int
- statusNum int
- )
- year, month, day := time.Now().Date()
- thisMonth := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
- if queryType == model.LastYearPerMonth {
- count = model.MonthNumPerYear
- } else if queryType == model.LastMonthPerDay {
- //_, _, count = thisMonth.AddDate(0, 0, -1).Date()
- count = model.DayNumPerMonth
- } else if queryType == model.LastYearPerDay {
- count = model.DayNumPerYear
- }
- for i := count; i >= 1; i-- {
- if queryType == model.LastYearPerMonth {
- since = thisMonth.AddDate(0, -i, 0)
- until = thisMonth.AddDate(0, -i+1, 0)
- } else if queryType == model.LastMonthPerDay {
- since = thisMonth.AddDate(0, 0, -i)
- until = thisMonth.AddDate(0, 0, -i+1)
- } else if queryType == model.LastYearPerDay {
- since = thisMonth.AddDate(0, 0, -i)
- until = thisMonth.AddDate(0, 0, -i+1)
- }
- /*if totalNum, statusNum, pipelineTime, err = s.QueryProjectPipelines(c, req, since, until); err != nil {
- log.Error("QueryProjectPipelines err:%+v", err)
- return
- }*/
- if totalNum, statusNum, pipelineTime, err = s.QueryPipelinesFromDB(c, req, since, until); err != nil {
- log.Error("QueryPipelinesFromDB err:%+v", err)
- return
- }
- avgTotalTime = utils.CalAverageTime(req.StatisticsType, pipelineTime.DurationList)
- avgPendingTime = utils.CalAverageTime(req.StatisticsType, pipelineTime.PendingList)
- avgRunningTime = utils.CalAverageTime(req.StatisticsType, pipelineTime.RunningList)
- perData = &model.PipelineDataAvg{
- TotalItem: totalNum,
- TotalStatusItem: statusNum,
- AvgDurationTime: avgTotalTime,
- AvgPendingTime: avgPendingTime,
- AvgRunningTime: avgRunningTime,
- MaxDurationTime: pipelineTime.DurationMax,
- MinDurationTime: pipelineTime.DurationMin,
- MaxPendingTime: pipelineTime.PendingMax,
- MinPendingTime: pipelineTime.PendingMin,
- MaxRunningTime: pipelineTime.RunningMax,
- MinRunningTime: pipelineTime.RunningMin,
- StartTime: since.Format(layout),
- EndTime: until.Format(layout),
- }
- resp = append(resp, perData)
- allNum = allNum + totalNum
- allStatusNum = allStatusNum + statusNum
- pendingTimeListAll = utils.CombineSlice(pendingTimeListAll, pipelineTime.PendingList)
- runningTimeListAll = utils.CombineSlice(runningTimeListAll, pipelineTime.RunningList)
- durationTimeListAll = utils.CombineSlice(durationTimeListAll, pipelineTime.DurationList)
- }
- avgDurationTime = utils.CalAverageTime(req.StatisticsType, durationTimeListAll)
- avgPendingTime = utils.CalAverageTime(req.StatisticsType, pendingTimeListAll)
- avgRunningTime = utils.CalAverageTime(req.StatisticsType, runningTimeListAll)
- log.Info("avgDurationTime: %v, avgPendingTime: %v, avgRunningTime: %v", avgDurationTime, avgPendingTime, avgRunningTime)
- return
- }
- // QueryProjectPipelines ...
- func (s *Service) QueryProjectPipelines(c context.Context, req *model.PipelineDataReq, since, until time.Time) (totalNum, statusNum int, pipelineTime *model.PipelineTime, err error) {
- var (
- pipelineList gitlab.PipelineList
- pipeline *gitlab.Pipeline
- resp *gitlab.Response
- startQuery bool
- meetTime bool
- projectID = req.ProjectID
- pendingTime float64
- runningTime float64
- totalTime float64
- )
- pipelineTime = &model.PipelineTime{}
- opt := &gitlab.ListProjectPipelinesOptions{}
- if _, resp, err = s.gitlab.ListProjectPipelines(1, projectID, ""); err != nil {
- log.Error("ListProjectPipelines err: %+v", err)
- return
- }
- page := 1
- for page <= resp.TotalPages {
- opt.ListOptions.Page = page
- if !startQuery && (!since.IsZero() || !until.IsZero()) {
- if pipelineList, _, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- log.Error("ListProjectPipelines err: %+v", err)
- return
- }
- if page == 1 && len(pipelineList) <= 0 {
- return
- }
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, pipelineList[0].ID); err != nil {
- return
- }
- if pipeline.CreatedAt.After(until) {
- page++
- continue
- } else {
- startQuery = true
- page--
- continue
- }
- }
- // start query
- if pipelineList, _, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- return
- }
- meetTime = true
- for _, v := range pipelineList {
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, v.ID); err != nil {
- return
- }
- createTime := pipeline.CreatedAt
- if !since.IsZero() || !until.IsZero() {
- meetTime = createTime.After(since) && createTime.Before(until)
- }
- //the pipeline is we need
- if meetTime {
- totalNum = totalNum + 1
- if req.Branch != "" && req.Branch != pipeline.Ref {
- continue
- } else if req.User != "" && req.User != pipeline.User.Name {
- continue
- } else if req.State != "" && req.State != pipeline.Status {
- continue
- }
- statusNum = statusNum + 1
- if pipeline.Status != "cancel" {
- if pipeline.StartedAt == nil {
- pendingTime = 0
- runningTime = pipeline.FinishedAt.Sub(*pipeline.CreatedAt).Seconds()
- } else {
- pendingTime = pipeline.StartedAt.Sub(*pipeline.CreatedAt).Seconds()
- runningTime = pipeline.FinishedAt.Sub(*pipeline.StartedAt).Seconds()
- }
- totalTime = pipeline.FinishedAt.Sub(*pipeline.CreatedAt).Seconds()
- pipelineTime.PendingMax, pipelineTime.PendingMin = utils.CalSizeTime(pendingTime, pipelineTime.PendingMax, pipelineTime.PendingMin)
- pipelineTime.RunningMax, pipelineTime.RunningMin = utils.CalSizeTime(runningTime, pipelineTime.RunningMax, pipelineTime.RunningMin)
- pipelineTime.DurationMax, pipelineTime.DurationMin = utils.CalSizeTime(totalTime, pipelineTime.DurationMax, pipelineTime.DurationMin)
- pipelineTime.PendingList = append(pipelineTime.PendingList, pendingTime)
- pipelineTime.RunningList = append(pipelineTime.RunningList, runningTime)
- pipelineTime.DurationList = append(pipelineTime.DurationList, totalTime)
- }
- }
- // time is over, so return
- if (!since.IsZero() || !until.IsZero()) && createTime.Before(since) {
- return
- }
- }
- page++
- }
- return
- }
- // QueryPipelinesFromDB ...
- func (s *Service) QueryPipelinesFromDB(c context.Context, req *model.PipelineDataReq, since, until time.Time) (totalNum, statusNum int, pipelineTime *model.PipelineTime, err error) {
- var (
- fmtLayout = `%d-%d-%d 00:00:00`
- pipelines []*model.StatisticsPipeline
- projectID = req.ProjectID
- pendingTime float64
- runningTime float64
- totalTime float64
- )
- pipelineTime = &model.PipelineTime{}
- sinceStr := fmt.Sprintf(fmtLayout, since.Year(), since.Month(), since.Day())
- untilStr := fmt.Sprintf(fmtLayout, until.Year(), until.Month(), until.Day())
- if totalNum, statusNum, pipelines, err = s.dao.QueryPipelinesByTime(projectID, req, sinceStr, untilStr); err != nil {
- return
- }
- for _, pipeline := range pipelines {
- if pipeline.Status == model.StatusCancel {
- continue
- }
- if pipeline.FinishedAt == nil {
- continue
- }
- if pipeline.StartedAt == nil {
- pendingTime = 0
- runningTime = pipeline.FinishedAt.Sub(*pipeline.CreatedAt).Seconds()
- } else {
- pendingTime = pipeline.StartedAt.Sub(*pipeline.CreatedAt).Seconds()
- runningTime = pipeline.FinishedAt.Sub(*pipeline.StartedAt).Seconds()
- }
- totalTime = pipeline.FinishedAt.Sub(*pipeline.CreatedAt).Seconds()
- pipelineTime.PendingMax, pipelineTime.PendingMin = utils.CalSizeTime(pendingTime, pipelineTime.PendingMax, pipelineTime.PendingMin)
- pipelineTime.RunningMax, pipelineTime.RunningMin = utils.CalSizeTime(runningTime, pipelineTime.RunningMax, pipelineTime.RunningMin)
- pipelineTime.DurationMax, pipelineTime.DurationMin = utils.CalSizeTime(totalTime, pipelineTime.DurationMax, pipelineTime.DurationMin)
- pipelineTime.PendingList = append(pipelineTime.PendingList, pendingTime)
- pipelineTime.RunningList = append(pipelineTime.RunningList, runningTime)
- pipelineTime.DurationList = append(pipelineTime.DurationList, totalTime)
- }
- return
- }
- //alertProjectPipelineProc cron func
- func (s *Service) alertProjectPipelineProc() {
- for _, alert := range conf.Conf.Property.Git.AlertPipeline {
- projectId := alert.ProjectID
- runningTimeout := alert.RunningTimeout
- runningRate := alert.RunningRate
- runningThreshold := alert.RunningThreshold
- pendingTimeout := alert.PendingTimeout
- pendingThreshold := alert.PendingThreshold
- go func() {
- var err error
- if err = s.PipelineAlert(context.TODO(), projectId, runningTimeout, runningThreshold, runningRate, gitlab.Running); err != nil {
- log.Error("PipelineAlert Running (%+v)", err)
- }
- if err = s.PipelineAlert(context.TODO(), projectId, pendingTimeout, pendingThreshold, 0, gitlab.Pending); err != nil {
- log.Error("PipelineAlert Pending (%+v)", err)
- }
- }()
- }
- }
- //PipelineAlert ...
- func (s *Service) PipelineAlert(c context.Context, projectID, timeout, threshold, rate int, status gitlab.BuildStateValue) (err error) {
- var (
- layout = "2006-01-02 15:04:05"
- pipeline *gitlab.Pipeline
- timeoutNum int
- message string
- pipelineurl string
- durationTime float64
- pipelineSUM int
- timeoutPipeline string
- pipelineList gitlab.PipelineList
- resp *gitlab.Response
- projectInfo *model.ProjectInfo
- userlist = conf.Conf.Property.Git.UserList
- w = wechat.New(s.dao)
- sendMessage = false
- )
- if projectInfo, err = s.dao.ProjectInfoByID(projectID); err != nil {
- return
- }
- repo := projectInfo.Repo
- if len(repo) > len(_gitSSH) {
- repo = repo[len(_gitSSH) : len(repo)-len(_gitSSHTail)]
- repo = _gitHTTP + repo
- }
- timeNow := time.Now().Format(layout)
- message = fmt.Sprintf("[SAGA]Pipeline 告警 %v\n项目:%s\n", timeNow, repo)
- for page := 1; ; page++ {
- if pipelineList, resp, err = s.git.ListProjectPipelines(page, projectID, status); err != nil {
- return
- }
- for _, item := range pipelineList {
- pipelineSUM += 1
- if pipeline, _, err = s.git.GetPipeline(projectID, item.ID); err != nil {
- return
- }
- if status == gitlab.Pending {
- durationTime = pipeline.UpdatedAt.Sub(*pipeline.CreatedAt).Minutes()
- } else if status == gitlab.Running {
- //此处时间计算换成job
- if durationTime, err = s.PipelineRunningTime(projectID, item.ID); err != nil {
- return
- }
- }
- if int(durationTime) >= timeout {
- timeoutNum += 1
- pipelineurl = fmt.Sprintf("%d. %s/pipelines/%d (%vmin)\n", timeoutNum, repo, pipeline.ID, int(durationTime))
- timeoutPipeline += pipelineurl
- }
- }
- if resp.NextPage == 0 {
- break
- }
- }
- if timeoutPipeline != "" {
- message += fmt.Sprintf(`列表(url|%s时间):%s%s`, status, "\n", timeoutPipeline)
- }
- if pipelineSUM > 0 {
- message += fmt.Sprintf(`状态:%s 总数为%d个`, status, pipelineSUM)
- }
- if status == gitlab.Pending {
- var alertMessage string
- message += fmt.Sprintf(`%s告警:`, "\n")
- if pipelineSUM >= threshold {
- alertMessage = fmt.Sprintf(`[ 数量(%d)>=警戒值(%d) ]`, pipelineSUM, threshold)
- sendMessage = true
- }
- message += alertMessage
- if timeoutNum >= 1 {
- if alertMessage != "" {
- message = message[:strings.LastIndex(message, " ]")] + fmt.Sprintf(`,%s时间>=警戒值(%d) ]`, status, timeout)
- } else {
- message += fmt.Sprintf(`[ %s时间>=警戒值(%d) ]`, status, timeout)
- }
- sendMessage = true
- }
- }
- if status == gitlab.Running && timeoutNum >= threshold {
- sendMessage = true
- message += fmt.Sprintf(`,时间>%dmin为%d个%s告警:[ 数量(%d)>=警戒值(%d) ]`, timeout, timeoutNum, "\n", timeoutNum, threshold)
- if timeoutNum*100/pipelineSUM >= rate {
- message = message[:strings.LastIndex(message, " ]")] + fmt.Sprintf(`,比例(%v%s)>=警戒值%d%s ]`, timeoutNum*100/pipelineSUM, "%", rate, "%")
- }
- }
- if sendMessage {
- return w.PushMsg(c, userlist, message)
- }
- return
- }
- //PipelineRunningTime ...
- func (s *Service) PipelineRunningTime(projectID, pipelineID int) (durationTime float64, err error) {
- var jobList []*gitlab.Job
- if jobList, _, err = s.git.ListPipelineJobs(nil, projectID, pipelineID); err != nil {
- return
- }
- for _, job := range jobList {
- if job.Status != _manualJob && job.Name != _androidScheduleJob && job.Name != _iosScheduleJob {
- if job.FinishedAt != nil && job.StartedAt != nil {
- durationTime += job.FinishedAt.Sub(*job.StartedAt).Minutes()
- } else if job.StartedAt != nil {
- durationTime += time.Since(*job.StartedAt).Minutes()
- }
- }
- }
- return
- }
- /*-------------------------------------- sync pipeline ----------------------------------------*/
- // SyncProjectPipelines ...
- func (s *Service) SyncProjectPipelines(projectID int) (result *model.SyncResult, err error) {
- var (
- //syncAllTime = conf.Conf.Property.SyncData.SyncAllTime
- syncAllTime = false
- since *time.Time
- until *time.Time
- projectInfo *model.ProjectInfo
- )
- if projectInfo, err = s.dao.ProjectInfoByID(projectID); err != nil {
- return
- }
- if !syncAllTime {
- since, until = utils.CalSyncTime()
- log.Info("sync project id(%d), name(%s) pipeline, time since: %v, until: %v", projectID, projectInfo.Name, since, until)
- if result, err = s.SyncProjectPipelinesByTime(projectID, projectInfo.Name, *since, *until); err != nil {
- return
- }
- } else {
- log.Info("sync project id(%d), name(%s) pipeline", projectID, projectInfo.Name)
- if result, err = s.SyncProjectAllPipelines(projectID, projectInfo.Name); err != nil {
- return
- }
- }
- return
- }
- // SyncProjectPipelinesByTime ...
- func (s *Service) SyncProjectPipelinesByTime(projectID int, projectName string, since, until time.Time) (result *model.SyncResult, err error) {
- var (
- pipelines gitlab.PipelineList
- pipeline *gitlab.Pipeline
- resp *gitlab.Response
- startQuery bool
- )
- result = &model.SyncResult{}
- if _, resp, err = s.gitlab.ListProjectPipelines(1, projectID, ""); err != nil {
- return
- }
- page := 1
- for page <= resp.TotalPages {
- result.TotalPage++
- if !startQuery {
- if pipelines, resp, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- return
- }
- if page == 1 && len(pipelines) <= 0 {
- return
- }
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, pipelines[0].ID); err != nil {
- return
- }
- if pipeline.CreatedAt.After(until) {
- page++
- continue
- } else {
- startQuery = true
- page--
- continue
- }
- }
- // start query
- if pipelines, _, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- return
- }
- for _, v := range pipelines {
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, v.ID); err != nil {
- return
- }
- createTime := pipeline.CreatedAt
- if createTime.After(since) && createTime.Before(until) {
- if err = s.structureDBPipeline(projectID, projectName, pipeline); err != nil {
- log.Error("pipeline Save Database err: projectID(%d), PipelineID(%d)", projectID, pipeline.ID)
- err = nil
- errData := &model.FailData{
- ChildID: pipeline.ID,
- }
- result.FailData = append(result.FailData, errData)
- continue
- }
- result.TotalNum++
- }
- if createTime.Before(since) {
- return
- }
- }
- page++
- }
- return
- }
- // SyncProjectAllPipelines ...
- func (s *Service) SyncProjectAllPipelines(projectID int, projectName string) (result *model.SyncResult, err error) {
- var (
- pipelines gitlab.PipelineList
- pipeline *gitlab.Pipeline
- resp *gitlab.Response
- )
- result = &model.SyncResult{}
- for page := 1; ; page++ {
- result.TotalPage++
- if pipelines, resp, err = s.gitlab.ListProjectPipelines(page, projectID, ""); err != nil {
- return
- }
- for _, v := range pipelines {
- if pipeline, _, err = s.gitlab.GetPipeline(projectID, v.ID); err != nil {
- return
- }
- if err = s.structureDBPipeline(projectID, projectName, pipeline); err != nil {
- log.Error("pipeline Save Database err: projectID(%d), PipelineID(%d)", projectID, pipeline.ID)
- err = nil
- errData := &model.FailData{
- ChildID: pipeline.ID,
- }
- result.FailData = append(result.FailData, errData)
- continue
- }
- result.TotalNum++
- }
- if resp.NextPage == 0 {
- break
- }
- }
- return
- }
- // structureDBPipeline ...
- func (s *Service) structureDBPipeline(projectID int, projectName string, pipeline *gitlab.Pipeline) (err error) {
- statisticPipeline := &model.StatisticsPipeline{
- PipelineID: pipeline.ID,
- ProjectID: projectID,
- ProjectName: projectName,
- Status: pipeline.Status,
- Ref: pipeline.Ref,
- Tag: pipeline.Tag,
- User: pipeline.User.Name,
- CreatedAt: pipeline.CreatedAt,
- UpdatedAt: pipeline.UpdatedAt,
- StartedAt: pipeline.StartedAt,
- FinishedAt: pipeline.FinishedAt,
- CommittedAt: pipeline.CommittedAt,
- Coverage: pipeline.Coverage,
- Duration: pipeline.Duration,
- DurationTime: 0,
- }
- return s.SaveDatabasePipeline(statisticPipeline)
- }
- // SaveDatabasePipeline ...
- func (s *Service) SaveDatabasePipeline(pipelineDB *model.StatisticsPipeline) (err error) {
- var total int
- if total, err = s.dao.HasPipeline(pipelineDB.ProjectID, pipelineDB.PipelineID); err != nil {
- log.Error("SaveDatabasePipeline HasPipeline(%+v)", err)
- return
- }
- // found only one, so update
- if total == 1 {
- if err = s.dao.UpdatePipeline(pipelineDB.ProjectID, pipelineDB.PipelineID, pipelineDB); err != nil {
- log.Error("SaveDatabasePipeline UpdatePipeline err(%+v)", err)
- return
- }
- return
- } else if total > 1 {
- // found repeated row, this situation will not exist under normal
- log.Warn("SaveDatabasePipeline pipeline has more rows(%d)", total)
- return
- }
- // insert row now
- if err = s.dao.CreatePipeline(pipelineDB); err != nil {
- log.Error("SaveDatabasePipeline CreatePipeline err(%+v)", err)
- return
- }
- return
- }
|