mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 11:28:24 +00:00 
			
		
		
		
	add most tables
This commit is contained in:
		
							
								
								
									
										289
									
								
								models/bots/build.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										289
									
								
								models/bots/build.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,289 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package bots | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	"code.gitea.io/gitea/models/webhook" | ||||
| 	"code.gitea.io/gitea/modules/log" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
|  | ||||
| 	"github.com/google/uuid" | ||||
| 	"xorm.io/builder" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	db.RegisterModel(new(Build)) | ||||
| 	db.RegisterModel(new(BuildIndex)) | ||||
| } | ||||
|  | ||||
| // BuildStatus represents a build status | ||||
| type BuildStatus int | ||||
|  | ||||
| // enumerate all the statuses of bot build | ||||
| const ( | ||||
| 	BuildPending  BuildStatus = iota // wait for assign | ||||
| 	BuildAssigned                    // assigned to a runner | ||||
| 	BuildRunning                     // running | ||||
| 	BuildFailed | ||||
| 	BuildFinished | ||||
| 	BuildCanceled | ||||
| 	BuildTimeout | ||||
| ) | ||||
|  | ||||
| func (status BuildStatus) IsPending() bool { | ||||
| 	return status == BuildPending || status == BuildAssigned | ||||
| } | ||||
|  | ||||
| func (status BuildStatus) IsRunning() bool { | ||||
| 	return status == BuildRunning | ||||
| } | ||||
|  | ||||
| func (status BuildStatus) IsFailed() bool { | ||||
| 	return status == BuildFailed || status == BuildCanceled || status == BuildTimeout | ||||
| } | ||||
|  | ||||
| func (status BuildStatus) IsSuccess() bool { | ||||
| 	return status == BuildFinished | ||||
| } | ||||
|  | ||||
| // Build represnets bot build task | ||||
| type Build struct { | ||||
| 	ID            int64 | ||||
| 	Title         string | ||||
| 	UUID          string `xorm:"CHAR(36)"` | ||||
| 	Index         int64  `xorm:"index unique(repo_index)"` | ||||
| 	RepoID        int64  `xorm:"index unique(repo_index)"` | ||||
| 	TriggerUserID int64 | ||||
| 	TriggerUser   *user_model.User `xorm:"-"` | ||||
| 	Ref           string | ||||
| 	CommitSHA     string | ||||
| 	Event         webhook.HookEventType | ||||
| 	Token         string             // token for this task | ||||
| 	Grant         string             // permissions for this task | ||||
| 	EventPayload  string             `xorm:"LONGTEXT"` | ||||
| 	RunnerID      int64              `xorm:"index"` | ||||
| 	Status        BuildStatus        `xorm:"index"` | ||||
| 	Created       timeutil.TimeStamp `xorm:"created"` | ||||
| 	StartTime     timeutil.TimeStamp | ||||
| 	EndTime       timeutil.TimeStamp | ||||
| 	Updated       timeutil.TimeStamp `xorm:"updated"` | ||||
| } | ||||
|  | ||||
| // TableName represents a bot build | ||||
| func (Build) TableName() string { | ||||
| 	return "bots_build" | ||||
| } | ||||
|  | ||||
| func (t *Build) HTMLURL() string { | ||||
| 	return fmt.Sprintf("") | ||||
| } | ||||
|  | ||||
| func updateRepoBuildsNumbers(ctx context.Context, repo *repo_model.Repository) error { | ||||
| 	_, err := db.GetEngine(ctx).ID(repo.ID). | ||||
| 		SetExpr("num_builds", | ||||
| 			builder.Select("count(*)").From("bots_build"). | ||||
| 				Where(builder.Eq{"repo_id": repo.ID}), | ||||
| 		). | ||||
| 		SetExpr("num_closed_builds", | ||||
| 			builder.Select("count(*)").From("bots_build"). | ||||
| 				Where(builder.Eq{ | ||||
| 					"repo_id": repo.ID, | ||||
| 				}.And( | ||||
| 					builder.In("status", BuildFailed, BuildCanceled, BuildTimeout, BuildFinished), | ||||
| 				), | ||||
| 				), | ||||
| 		). | ||||
| 		Update(repo) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // InsertBuild inserts a bot build task | ||||
| func InsertBuild(t *Build, workflowsStatuses map[string]map[string]BuildStatus) error { | ||||
| 	if t.UUID == "" { | ||||
| 		t.UUID = uuid.New().String() | ||||
| 	} | ||||
| 	index, err := db.GetNextResourceIndex("bots_build_index", t.RepoID) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	t.Index = index | ||||
|  | ||||
| 	ctx, commiter, err := db.TxContext() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer commiter.Close() | ||||
|  | ||||
| 	if err := db.Insert(ctx, t); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := updateRepoBuildsNumbers(ctx, &repo_model.Repository{ID: t.RepoID}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	var buildJobs []BuildJob | ||||
| 	for filename, workflow := range workflowsStatuses { | ||||
| 		for job, status := range workflow { | ||||
| 			buildJobs = append(buildJobs, BuildJob{ | ||||
| 				BuildID:  t.ID, | ||||
| 				Filename: filename, | ||||
| 				Jobname:  job, | ||||
| 				Status:   status, | ||||
| 			}) | ||||
| 		} | ||||
| 	} | ||||
| 	if err := db.Insert(ctx, buildJobs); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := commiter.Commit(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := CreateBuildLog(t.ID); err != nil { | ||||
| 		log.Error("create build log for %d table failed, will try it again when received logs", t.ID) | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| // UpdateBuild updates bot build | ||||
| func UpdateBuild(t *Build, cols ...string) error { | ||||
| 	_, err := db.GetEngine(db.DefaultContext).ID(t.ID).Cols(cols...).Update(t) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // ErrBuildNotExist represents an error for bot build not exist | ||||
| type ErrBuildNotExist struct { | ||||
| 	RepoID int64 | ||||
| 	Index  int64 | ||||
| 	UUID   string | ||||
| } | ||||
|  | ||||
| func (err ErrBuildNotExist) Error() string { | ||||
| 	return fmt.Sprintf("Bot build [%s] is not exist", err.UUID) | ||||
| } | ||||
|  | ||||
| // GetBuildByUUID gets bot build by uuid | ||||
| func GetBuildByUUID(buildUUID string) (*Build, error) { | ||||
| 	var build Build | ||||
| 	has, err := db.GetEngine(db.DefaultContext).Where("uuid=?", buildUUID).Get(&build) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} else if !has { | ||||
| 		return nil, ErrBuildNotExist{ | ||||
| 			UUID: buildUUID, | ||||
| 		} | ||||
| 	} | ||||
| 	return &build, nil | ||||
| } | ||||
|  | ||||
| // GetCurBuildByID return the build for the bot | ||||
| func GetCurBuildByID(runnerID int64) (*Build, error) { | ||||
| 	var builds []Build | ||||
| 	err := db.GetEngine(db.DefaultContext). | ||||
| 		Where("runner_id=?", runnerID). | ||||
| 		And("status=?", BuildPending). | ||||
| 		Asc("created"). | ||||
| 		Find(&builds) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(builds) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	return &builds[0], err | ||||
| } | ||||
|  | ||||
| // GetCurBuildByUUID return the task for the bot | ||||
| func GetCurBuildByUUID(runnerUUID string) (*Build, error) { | ||||
| 	runner, err := GetRunnerByUUID(runnerUUID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return GetCurBuildByID(runner.ID) | ||||
| } | ||||
|  | ||||
| func GetBuildByRepoAndIndex(repoID, index int64) (*Build, error) { | ||||
| 	var build Build | ||||
| 	has, err := db.GetEngine(db.DefaultContext).Where("repo_id=?", repoID). | ||||
| 		And("`index` = ?", index). | ||||
| 		Get(&build) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} else if !has { | ||||
| 		return nil, ErrBuildNotExist{ | ||||
| 			RepoID: repoID, | ||||
| 			Index:  index, | ||||
| 		} | ||||
| 	} | ||||
| 	return &build, nil | ||||
| } | ||||
|  | ||||
| // AssignBuildToRunner assign a build to a runner | ||||
| func AssignBuildToRunner(buildID int64, runnerID int64) error { | ||||
| 	cnt, err := db.GetEngine(db.DefaultContext). | ||||
| 		Where("runner_id=0"). | ||||
| 		And("id=?", buildID). | ||||
| 		Cols("runner_id"). | ||||
| 		Update(&Build{ | ||||
| 			RunnerID: runnerID, | ||||
| 		}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if cnt != 1 { | ||||
| 		return errors.New("assign faild") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type FindBuildOptions struct { | ||||
| 	db.ListOptions | ||||
| 	RepoID   int64 | ||||
| 	IsClosed util.OptionalBool | ||||
| } | ||||
|  | ||||
| func (opts FindBuildOptions) toConds() builder.Cond { | ||||
| 	cond := builder.NewCond() | ||||
| 	if opts.RepoID > 0 { | ||||
| 		cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) | ||||
| 	} | ||||
| 	if opts.IsClosed.IsTrue() { | ||||
| 		cond = cond.And(builder.Expr("status IN (?,?,?,?)", BuildCanceled, BuildFailed, BuildTimeout, BuildFinished)) | ||||
| 	} else if opts.IsClosed.IsFalse() { | ||||
| 		cond = cond.And(builder.Expr("status IN (?,?,?)", BuildPending, BuildAssigned, BuildRunning)) | ||||
| 	} | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
| func FindBuilds(opts FindBuildOptions) (BuildList, error) { | ||||
| 	sess := db.GetEngine(db.DefaultContext).Where(opts.toConds()) | ||||
| 	if opts.ListOptions.PageSize > 0 { | ||||
| 		skip, take := opts.GetSkipTake() | ||||
| 		sess.Limit(take, skip) | ||||
| 	} | ||||
| 	var builds []*Build | ||||
| 	return builds, sess.Find(&builds) | ||||
| } | ||||
|  | ||||
| func CountBuilds(opts FindBuildOptions) (int64, error) { | ||||
| 	return db.GetEngine(db.DefaultContext).Table("bots_build").Where(opts.toConds()).Count() | ||||
| } | ||||
|  | ||||
| type BuildIndex db.ResourceIndex | ||||
|  | ||||
| // TableName represents a bot build index | ||||
| func (BuildIndex) TableName() string { | ||||
| 	return "bots_build_index" | ||||
| } | ||||
							
								
								
									
										42
									
								
								models/bots/build_job.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								models/bots/build_job.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package bots | ||||
|  | ||||
| import ( | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| ) | ||||
|  | ||||
| type BuildJob struct { | ||||
| 	ID        int64 | ||||
| 	BuildID   int64 `xorm:"index"` | ||||
| 	Filename  string | ||||
| 	Jobname   string | ||||
| 	Status    BuildStatus | ||||
| 	LogToFile bool               // read log from database or from storage | ||||
| 	Created   timeutil.TimeStamp `xorm:"created"` | ||||
| } | ||||
|  | ||||
| func (bj BuildJob) TableName() string { | ||||
| 	return "bots_build_job" | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	db.RegisterModel(new(BuildJob)) | ||||
| } | ||||
|  | ||||
| func GetBuildWorkflows(buildID int64) (map[string]map[string]*BuildJob, error) { | ||||
| 	jobs := make(map[string]map[string]*BuildJob) | ||||
| 	err := db.GetEngine(db.DefaultContext).Iterate(new(BuildJob), func(idx int, bean interface{}) error { | ||||
| 		job := bean.(*BuildJob) | ||||
| 		_, ok := jobs[job.Filename] | ||||
| 		if !ok { | ||||
| 			jobs[job.Filename] = make(map[string]*BuildJob) | ||||
| 		} | ||||
| 		jobs[job.Filename][job.Jobname] = job | ||||
| 		return nil | ||||
| 	}) | ||||
| 	return jobs, err | ||||
| } | ||||
| @@ -9,13 +9,13 @@ import ( | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| ) | ||||
| 
 | ||||
| type TaskList []*Task | ||||
| type BuildList []*Build | ||||
| 
 | ||||
| // GetUserIDs returns a slice of user's id | ||||
| func (tasks TaskList) GetUserIDs() []int64 { | ||||
| func (builds BuildList) GetUserIDs() []int64 { | ||||
| 	userIDsMap := make(map[int64]struct{}) | ||||
| 	for _, task := range tasks { | ||||
| 		userIDsMap[task.TriggerUserID] = struct{}{} | ||||
| 	for _, build := range builds { | ||||
| 		userIDsMap[build.TriggerUserID] = struct{}{} | ||||
| 	} | ||||
| 	userIDs := make([]int64, 0, len(userIDsMap)) | ||||
| 	for userID := range userIDsMap { | ||||
| @@ -24,13 +24,13 @@ func (tasks TaskList) GetUserIDs() []int64 { | ||||
| 	return userIDs | ||||
| } | ||||
| 
 | ||||
| func (tasks TaskList) LoadTriggerUser() error { | ||||
| 	userIDs := tasks.GetUserIDs() | ||||
| func (builds BuildList) LoadTriggerUser() error { | ||||
| 	userIDs := builds.GetUserIDs() | ||||
| 	users := make(map[int64]*user_model.User, len(userIDs)) | ||||
| 	if err := db.GetEngine(db.DefaultContext).In("id", userIDs).Find(&users); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	for _, task := range tasks { | ||||
| 	for _, task := range builds { | ||||
| 		task.TriggerUser = users[task.TriggerUserID] | ||||
| 	} | ||||
| 	return nil | ||||
							
								
								
									
										43
									
								
								models/bots/build_log.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								models/bots/build_log.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package bots | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| ) | ||||
|  | ||||
| // BuildLog represents a build's log, every build has a standalone table | ||||
| type BuildLog struct { | ||||
| 	ID         int64 | ||||
| 	BuildJobID int64 `xorm:"index"` | ||||
| 	LineNumber int | ||||
| 	Content    string             `xorm:"LONGTEXT"` | ||||
| 	Created    timeutil.TimeStamp `xorm:"created"` | ||||
| } | ||||
|  | ||||
| func init() { | ||||
| 	db.RegisterModel(new(BuildLog)) | ||||
| } | ||||
|  | ||||
| func GetBuildLogTableName(buildID int64) string { | ||||
| 	return fmt.Sprintf("bots_build_log_%d", buildID) | ||||
| } | ||||
|  | ||||
| // CreateBuildLog table for a build | ||||
| func CreateBuildLog(buildID int64) error { | ||||
| 	return db.GetEngine(db.DefaultContext). | ||||
| 		Table(GetBuildLogTableName(buildID)). | ||||
| 		Sync2(new(BuildLog)) | ||||
| } | ||||
|  | ||||
| func GetBuildLogs(buildID, jobID int64) (logs []BuildLog, err error) { | ||||
| 	err = db.GetEngine(db.DefaultContext).Table(GetBuildLogTableName(buildID)). | ||||
| 		Where("build_job_id=?", jobID). | ||||
| 		Find(&logs) | ||||
| 	return | ||||
| } | ||||
| @@ -1,266 +0,0 @@ | ||||
| // Copyright 2022 The Gitea Authors. All rights reserved. | ||||
| // Use of this source code is governed by a MIT-style | ||||
| // license that can be found in the LICENSE file. | ||||
|  | ||||
| package bots | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"errors" | ||||
| 	"fmt" | ||||
|  | ||||
| 	"code.gitea.io/gitea/models/db" | ||||
| 	repo_model "code.gitea.io/gitea/models/repo" | ||||
| 	user_model "code.gitea.io/gitea/models/user" | ||||
| 	"code.gitea.io/gitea/models/webhook" | ||||
| 	"code.gitea.io/gitea/modules/timeutil" | ||||
| 	"code.gitea.io/gitea/modules/util" | ||||
|  | ||||
| 	"github.com/google/uuid" | ||||
| 	"xorm.io/builder" | ||||
| ) | ||||
|  | ||||
| func init() { | ||||
| 	db.RegisterModel(new(Task)) | ||||
| 	db.RegisterModel(new(BuildIndex)) | ||||
| } | ||||
|  | ||||
| // TaskStatus represents a task status | ||||
| type TaskStatus int | ||||
|  | ||||
| // enumerate all the statuses of bot task | ||||
| const ( | ||||
| 	TaskPending  TaskStatus = iota // wait for assign | ||||
| 	TaskAssigned                   // assigned to a runner | ||||
| 	TaskRunning                    // running | ||||
| 	TaskFailed | ||||
| 	TaskFinished | ||||
| 	TaskCanceled | ||||
| 	TaskTimeout | ||||
| ) | ||||
|  | ||||
| // Task represnets bot tasks | ||||
| type Task struct { | ||||
| 	ID                int64 | ||||
| 	Title             string | ||||
| 	UUID              string `xorm:"CHAR(36)"` | ||||
| 	Index             int64  `xorm:"index unique(repo_index)"` | ||||
| 	RepoID            int64  `xorm:"index unique(repo_index)"` | ||||
| 	TriggerUserID     int64 | ||||
| 	TriggerUser       *user_model.User `xorm:"-"` | ||||
| 	Ref               string | ||||
| 	CommitSHA         string | ||||
| 	Event             webhook.HookEventType | ||||
| 	Token             string                           // token for this task | ||||
| 	Grant             string                           // permissions for this task | ||||
| 	EventPayload      string                           `xorm:"LONGTEXT"` | ||||
| 	RunnerID          int64                            `xorm:"index"` | ||||
| 	Status            TaskStatus                       `xorm:"index"` | ||||
| 	WorkflowsStatuses map[string]map[string]TaskStatus `xorm:"LONGTEXT"` | ||||
| 	Created           timeutil.TimeStamp               `xorm:"created"` | ||||
| 	StartTime         timeutil.TimeStamp | ||||
| 	EndTime           timeutil.TimeStamp | ||||
| 	Updated           timeutil.TimeStamp `xorm:"updated"` | ||||
| } | ||||
|  | ||||
| func (t *Task) IsPending() bool { | ||||
| 	return t.Status == TaskPending || t.Status == TaskAssigned | ||||
| } | ||||
|  | ||||
| func (t *Task) IsRunning() bool { | ||||
| 	return t.Status == TaskRunning | ||||
| } | ||||
|  | ||||
| func (t *Task) IsFailed() bool { | ||||
| 	return t.Status == TaskFailed || t.Status == TaskCanceled || t.Status == TaskTimeout | ||||
| } | ||||
|  | ||||
| func (t *Task) IsSuccess() bool { | ||||
| 	return t.Status == TaskFinished | ||||
| } | ||||
|  | ||||
| // TableName represents a bot task | ||||
| func (Task) TableName() string { | ||||
| 	return "bots_task" | ||||
| } | ||||
|  | ||||
| func (t *Task) HTMLURL() string { | ||||
| 	return fmt.Sprintf("") | ||||
| } | ||||
|  | ||||
| func updateRepoBuildsNumbers(ctx context.Context, repo *repo_model.Repository) error { | ||||
| 	_, err := db.GetEngine(ctx).ID(repo.ID). | ||||
| 		SetExpr("num_builds", | ||||
| 			builder.Select("count(*)").From("bots_task"). | ||||
| 				Where(builder.Eq{"repo_id": repo.ID}), | ||||
| 		). | ||||
| 		SetExpr("num_closed_builds", | ||||
| 			builder.Select("count(*)").From("bots_task"). | ||||
| 				Where(builder.Eq{ | ||||
| 					"repo_id": repo.ID, | ||||
| 				}.And( | ||||
| 					builder.In("status", TaskFailed, TaskCanceled, TaskTimeout, TaskFinished), | ||||
| 				), | ||||
| 				), | ||||
| 		). | ||||
| 		Update(repo) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // InsertTask inserts a bot task | ||||
| func InsertTask(t *Task) error { | ||||
| 	if t.UUID == "" { | ||||
| 		t.UUID = uuid.New().String() | ||||
| 	} | ||||
| 	index, err := db.GetNextResourceIndex("build_index", t.RepoID) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	t.Index = index | ||||
|  | ||||
| 	ctx, commiter, err := db.TxContext() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	defer commiter.Close() | ||||
|  | ||||
| 	if err := db.Insert(ctx, t); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if err := updateRepoBuildsNumbers(ctx, &repo_model.Repository{ID: t.RepoID}); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return commiter.Commit() | ||||
| } | ||||
|  | ||||
| // UpdateTask updates bot task | ||||
| func UpdateTask(t *Task, cols ...string) error { | ||||
| 	_, err := db.GetEngine(db.DefaultContext).ID(t.ID).Cols(cols...).Update(t) | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| // ErrTaskNotExist represents an error for bot task not exist | ||||
| type ErrTaskNotExist struct { | ||||
| 	RepoID int64 | ||||
| 	Index  int64 | ||||
| 	UUID   string | ||||
| } | ||||
|  | ||||
| func (err ErrTaskNotExist) Error() string { | ||||
| 	return fmt.Sprintf("Bot task [%s] is not exist", err.UUID) | ||||
| } | ||||
|  | ||||
| // GetTaskByUUID gets bot task by uuid | ||||
| func GetTaskByUUID(taskUUID string) (*Task, error) { | ||||
| 	var task Task | ||||
| 	has, err := db.GetEngine(db.DefaultContext).Where("uuid=?", taskUUID).Get(&task) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} else if !has { | ||||
| 		return nil, ErrTaskNotExist{ | ||||
| 			UUID: taskUUID, | ||||
| 		} | ||||
| 	} | ||||
| 	return &task, nil | ||||
| } | ||||
|  | ||||
| // GetCurTaskByID return the task for the bot | ||||
| func GetCurTaskByID(runnerID int64) (*Task, error) { | ||||
| 	var tasks []Task | ||||
| 	// FIXME: for test, just return all tasks | ||||
| 	err := db.GetEngine(db.DefaultContext).Where("status=?", TaskPending).Find(&tasks) | ||||
| 	// err := x.Where("runner_id = ?", botID). | ||||
| 	// And("status=?", BotTaskPending). | ||||
| 	// Find(&tasks) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	if len(tasks) == 0 { | ||||
| 		return nil, nil | ||||
| 	} | ||||
| 	return &tasks[0], err | ||||
| } | ||||
|  | ||||
| // GetCurTaskByUUID return the task for the bot | ||||
| func GetCurTaskByUUID(runnerUUID string) (*Task, error) { | ||||
| 	runner, err := GetRunnerByUUID(runnerUUID) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} | ||||
| 	return GetCurTaskByID(runner.ID) | ||||
| } | ||||
|  | ||||
| func GetTaskByRepoAndIndex(repoID, index int64) (*Task, error) { | ||||
| 	var task Task | ||||
| 	has, err := db.GetEngine(db.DefaultContext).Where("repo_id=?", repoID). | ||||
| 		And("`index` = ?", index). | ||||
| 		Get(&task) | ||||
| 	if err != nil { | ||||
| 		return nil, err | ||||
| 	} else if !has { | ||||
| 		return nil, ErrTaskNotExist{ | ||||
| 			RepoID: repoID, | ||||
| 			Index:  index, | ||||
| 		} | ||||
| 	} | ||||
| 	return &task, nil | ||||
| } | ||||
|  | ||||
| // AssignTaskToRunner assign a task to a runner | ||||
| func AssignTaskToRunner(taskID int64, runnerID int64) error { | ||||
| 	cnt, err := db.GetEngine(db.DefaultContext). | ||||
| 		Where("runner_id=0"). | ||||
| 		And("id=?", taskID). | ||||
| 		Cols("runner_id"). | ||||
| 		Update(&Task{ | ||||
| 			RunnerID: runnerID, | ||||
| 		}) | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
| 	if cnt != 1 { | ||||
| 		return errors.New("assign faild") | ||||
| 	} | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| type FindTaskOptions struct { | ||||
| 	db.ListOptions | ||||
| 	RepoID   int64 | ||||
| 	IsClosed util.OptionalBool | ||||
| } | ||||
|  | ||||
| func (opts FindTaskOptions) toConds() builder.Cond { | ||||
| 	cond := builder.NewCond() | ||||
| 	if opts.RepoID > 0 { | ||||
| 		cond = cond.And(builder.Eq{"repo_id": opts.RepoID}) | ||||
| 	} | ||||
| 	if opts.IsClosed.IsTrue() { | ||||
| 		cond = cond.And(builder.Expr("status IN (?,?,?,?)", TaskCanceled, TaskFailed, TaskTimeout, TaskFinished)) | ||||
| 	} else if opts.IsClosed.IsFalse() { | ||||
| 		cond = cond.And(builder.Expr("status IN (?,?,?)", TaskPending, TaskAssigned, TaskRunning)) | ||||
| 	} | ||||
| 	return cond | ||||
| } | ||||
|  | ||||
| func FindTasks(opts FindTaskOptions) (TaskList, error) { | ||||
| 	sess := db.GetEngine(db.DefaultContext).Where(opts.toConds()) | ||||
| 	if opts.ListOptions.PageSize > 0 { | ||||
| 		skip, take := opts.GetSkipTake() | ||||
| 		sess.Limit(take, skip) | ||||
| 	} | ||||
| 	var tasks []*Task | ||||
| 	return tasks, sess.Find(&tasks) | ||||
| } | ||||
|  | ||||
| func CountTasks(opts FindTaskOptions) (int64, error) { | ||||
| 	return db.GetEngine(db.DefaultContext).Table("bots_task").Where(opts.toConds()).Count() | ||||
| } | ||||
|  | ||||
| type TaskStage struct{} | ||||
|  | ||||
| type StageStep struct{} | ||||
|  | ||||
| type BuildIndex db.ResourceIndex | ||||
		Reference in New Issue
	
	Block a user