diff --git a/README.md b/README.md index b6e7892c9..061ece70c 100644 --- a/README.md +++ b/README.md @@ -46,3 +46,6 @@ - 点击[这里](https://git.openi.org.cn/OpenI/aiforge/issues)在线提交问题(点击页面右上角绿色按钮**创建任务**) - 加入微信群实时交流,获得进一步的支持 + +## 启智社区小白训练营: +- 结合案例给大家详细讲解如何使用社区平台,帮助无技术背景的小白成长为启智社区达人 (https://git.openi.org.cn/zeizei/OpenI_Learning) diff --git a/go.mod b/go.mod index 337aabc8e..d9c12ea3a 100755 --- a/go.mod +++ b/go.mod @@ -56,6 +56,7 @@ require ( github.com/gomodule/redigo v2.0.0+incompatible github.com/google/go-github/v24 v24.0.1 github.com/gorilla/context v1.1.1 + github.com/gorilla/websocket v1.4.0 github.com/hashicorp/go-retryablehttp v0.6.6 // indirect github.com/huandu/xstrings v1.3.0 github.com/issue9/assert v1.3.2 // indirect diff --git a/go.sum b/go.sum index 7346b9050..9bae7932d 100755 --- a/go.sum +++ b/go.sum @@ -394,6 +394,7 @@ github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+ github.com/gorilla/sessions v1.1.1/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w= github.com/gorilla/sessions v1.2.0 h1:S7P+1Hm5V/AT9cjEcUD5uDaQSX0OE577aCXgoaKpYbQ= github.com/gorilla/sessions v1.2.0/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM= +github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= diff --git a/models/attachment.go b/models/attachment.go index d217a61a4..fd1df9e43 100755 --- a/models/attachment.go +++ b/models/attachment.go @@ -439,6 +439,19 @@ func GetModelArtsUserAttachments(userID int64) ([]*AttachmentUsername, error) { return getModelArtsUserAttachments(x, userID) } +func getModelArtsTrainAttachments(e Engine, userID int64) ([]*AttachmentUsername, error) { + attachments := make([]*AttachmentUsername, 0, 10) + if err := e.Table("attachment").Join("LEFT", "`user`", "attachment.uploader_id "+ + "= `user`.id").Where("attachment.type = ? and (uploader_id= ? or is_private = ?) and attachment.decompress_state = ?", TypeCloudBrainTwo, userID, false, DecompressStateDone).Find(&attachments); err != nil { + return nil, err + } + return attachments, nil +} + +func GetModelArtsTrainAttachments(userID int64) ([]*AttachmentUsername, error) { + return getModelArtsTrainAttachments(x, userID) +} + func CanDelAttachment(isSigned bool, user *User, attach *Attachment) bool { if !isSigned { return false diff --git a/models/cloudbrain.go b/models/cloudbrain.go index 509f4a9ed..5bf066413 100755 --- a/models/cloudbrain.go +++ b/models/cloudbrain.go @@ -19,6 +19,9 @@ type JobType string type ModelArtsJobStatus string const ( + NPUResource = "NPU" + GPUResource = "CPU/GPU" + JobWaiting CloudbrainStatus = "WAITING" JobStopped CloudbrainStatus = "STOPPED" JobSucceeded CloudbrainStatus = "SUCCEEDED" @@ -88,6 +91,9 @@ type Cloudbrain struct { UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` Duration int64 TrainJobDuration string + Image string //GPU镜像名称 + GpuQueue string //GPU类型即GPU队列 + ResourceSpecId int //GPU规格id DeletedAt time.Time `xorm:"deleted"` CanDebug bool `xorm:"-"` CanDel bool `xorm:"-"` @@ -204,6 +210,7 @@ type CloudbrainsOptions struct { JobType string VersionName string IsLatestVersion string + JobTypeNot bool } type TaskPod struct { @@ -888,9 +895,15 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*CloudbrainInfo, int64, error) { } if (opts.JobType) != "" { - cond = cond.And( - builder.Eq{"cloudbrain.job_type": opts.JobType}, - ) + if opts.JobTypeNot { + cond = cond.And( + builder.Neq{"cloudbrain.job_type": opts.JobType}, + ) + } else { + cond = cond.And( + builder.Eq{"cloudbrain.job_type": opts.JobType}, + ) + } } if (opts.IsLatestVersion) != "" { diff --git a/models/error.go b/models/error.go index 9d1c68658..46917e15e 100755 --- a/models/error.go +++ b/models/error.go @@ -1999,3 +1999,16 @@ func IsErrJobNotExist(err error) bool { func (err ErrJobNotExist) Error() string { return fmt.Sprintf("the job does not exist") } + +type ErrTagNotExist struct { + TagID int64 +} + +func (err ErrTagNotExist) Error() string { + return fmt.Sprintf("the tag does not exist") +} + +func IsErrTagNotExist(err error) bool { + _, ok := err.(ErrTagNotExist) + return ok +} diff --git a/models/issue.go b/models/issue.go index 7457fcd45..19f00d5f3 100755 --- a/models/issue.go +++ b/models/issue.go @@ -1397,6 +1397,8 @@ func getIssueStatsChunk(opts *IssueStatsOptions, issueIDs []int64) (*IssueStats, if opts.MilestoneID > 0 { sess.And("issue.milestone_id = ?", opts.MilestoneID) + } else if opts.MilestoneID == -1 { //only search for issues do not have milestone + sess.And("issue.milestone_id = ?", 0) } if opts.AssigneeID > 0 { diff --git a/models/issue_milestone.go b/models/issue_milestone.go index 464827445..a08bbf4dc 100644 --- a/models/issue_milestone.go +++ b/models/issue_milestone.go @@ -353,7 +353,7 @@ func GetMilestonesByRepoID(repoID int64, state api.StateType, listOptions ListOp } miles := make([]*Milestone, 0, listOptions.PageSize) - return miles, sess.Asc("deadline_unix").Asc("id").Find(&miles) + return miles, sess.Desc("id").Find(&miles) } // GetMilestones returns a list of milestones of given repository and status. diff --git a/models/models.go b/models/models.go index e8a71bbd8..a72ebe5db 100755 --- a/models/models.go +++ b/models/models.go @@ -134,6 +134,8 @@ func init() { new(BlockChain), new(RecommendOrg), new(AiModelManage), + new(OfficialTag), + new(OfficialTagRepos), ) tablesStatistic = append(tablesStatistic, diff --git a/models/repo.go b/models/repo.go index a4417e4bd..8070d7442 100755 --- a/models/repo.go +++ b/models/repo.go @@ -2470,6 +2470,12 @@ func GetBlockChainUnSuccessRepos() ([]*Repository, error) { Find(&repos) } +func (repo *Repository) UpdateBlockChain() error { + + _, err := x.Exec("UPDATE `repository` SET block_chain_status = ?, contract_address=? WHERE id = ?", repo.BlockChainStatus, repo.ContractAddress, repo.ID) + return err +} + func (repo *Repository) IncreaseCloneCnt() { sess := x.NewSession() defer sess.Close() diff --git a/models/repo_tag.go b/models/repo_tag.go new file mode 100644 index 000000000..76740bd76 --- /dev/null +++ b/models/repo_tag.go @@ -0,0 +1,163 @@ +package models + +import ( + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/timeutil" + "fmt" +) + +type OfficialTag struct { + ID int64 `xorm:"pk autoincr"` + Name string `xorm:"NOT NULL"` + Code string `xorm:"NOT NULL"` + Limit int `xorm:"NOT NULL default(-1)"` + Status int `xorm:"NOT NULL default(0)"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` +} + +type OfficialTagRepos struct { + ID int64 `xorm:"pk autoincr"` + OrgID int64 `xorm:"NOT NULL INDEX"` + TagID int64 `xorm:"NOT NULL"` + RepoID int64 `xorm:"NOT NULL INDEX"` + CreatedUnix timeutil.TimeStamp `xorm:"created"` + UpdatedUnix timeutil.TimeStamp `xorm:"updated"` +} + +type TagReposBrief struct { + RepoID int64 + RepoName string + TagID int64 +} + +type TagReposSelected struct { + RepoID int64 + RepoName string + Selected bool +} + +type TagsDetail struct { + TagId int64 + TagName string + TagLimit int + RepoList []Repository +} + +func GetTagByID(id int64) (*OfficialTag, error) { + r := &OfficialTag{ + ID: id, + } + has, err := x.Get(r) + if err != nil { + return nil, err + } else if !has { + return nil, ErrTagNotExist{0} + } + return r, nil +} + +func UpdateTagReposByID(tagID, orgID int64, repoIdList []int64) error { + sess := x.NewSession() + defer sess.Close() + + if err := sess.Begin(); err != nil { + return fmt.Errorf("UpdateTagReposByID[tagId: %d, orgID: %d,error:%v", tagID, orgID, err) + } + //delete old tag repos + r := &OfficialTagRepos{ + TagID: tagID, + OrgID: orgID, + } + _, err := sess.Delete(r) + if err != nil { + return err + } + + if len(repoIdList) == 0 { + return sess.Commit() + } + + //add new tag repos + data := make([]*OfficialTagRepos, 0) + for _, repoId := range repoIdList { + data = append(data, &OfficialTagRepos{ + OrgID: orgID, + TagID: tagID, + RepoID: repoId, + }) + } + _, err = sess.Insert(&data) + if err != nil { + sess.Rollback() + return err + } + return sess.Commit() +} + +func GetTagRepos(tagID, orgID int64) ([]TagReposSelected, error) { + t := make([]TagReposBrief, 0) + const SQLCmd = "select t1.id as repo_id,t1.name as repo_name,t2.id as tag_id from repository t1 left join official_tag_repos t2 on (t1.id = t2.repo_id and t2.tag_id = ?) where t1.owner_id = ? and t1.is_private = false order by t1.updated_unix desc" + + if err := x.SQL(SQLCmd, tagID, orgID).Find(&t); err != nil { + return nil, err + } + r := make([]TagReposSelected, 0) + for _, v := range t { + selected := false + if v.TagID > 0 { + selected = true + } + r = append(r, TagReposSelected{ + RepoID: v.RepoID, + RepoName: v.RepoName, + Selected: selected, + }) + } + return r, nil +} + +func GetAllOfficialTagRepos(orgID int64, isOwner bool) ([]TagsDetail, error) { + result := make([]TagsDetail, 0) + tags, err := GetAllOfficialTags() + if err != nil { + return nil, err + } + for _, tag := range tags { + repos, err := GetOfficialTagDetail(orgID, tag.ID) + if err != nil { + return nil, err + } + if len(repos) == 0 && !isOwner { + continue + } + result = append(result, TagsDetail{ + TagId: tag.ID, + TagName: tag.Name, + TagLimit: tag.Limit, + RepoList: repos, + }) + } + return result, nil +} + +func GetOfficialTagDetail(orgID, tagId int64) ([]Repository, error) { + t := make([]Repository, 0) + const SQLCmd = "select t2.* from official_tag_repos t1 inner join repository t2 on t1.repo_id = t2.id where t1.org_id = ? and t1.tag_id=? order by t2.updated_unix desc" + + if err := x.SQL(SQLCmd, orgID, tagId).Find(&t); err != nil { + return nil, err + } + return t, nil +} + +func GetAllOfficialTags() ([]OfficialTag, error) { + //todo redis? + o := make([]OfficialTag, 0) + err := x.Where("status = ?", 0).OrderBy("updated_unix desc").Find(&o) + if err != nil { + log.Error("GetAllOfficialTags error,%v", err) + return nil, err + } + return o, nil +} diff --git a/models/repo_watch.go b/models/repo_watch.go index 6bdef9c7f..1d6b7a31c 100644 --- a/models/repo_watch.go +++ b/models/repo_watch.go @@ -24,6 +24,8 @@ const ( RepoWatchModeAuto // 3 ) +var ActionChan = make(chan *Action, 200) + // Watch is connection request for receiving repository notification. type Watch struct { ID int64 `xorm:"pk autoincr"` @@ -277,9 +279,17 @@ func notifyWatchers(e Engine, actions ...*Action) error { // NotifyWatchers creates batch of actions for every watcher. func NotifyWatchers(actions ...*Action) error { + + producer(actions...) return notifyWatchers(x, actions...) } +func producer(actions ...*Action) { + for _, action := range actions { + ActionChan <- action + } +} + // NotifyWatchersActions creates batch of actions for every watcher. func NotifyWatchersActions(acts []*Action) error { sess := x.NewSession() diff --git a/models/user_business_analysis.go b/models/user_business_analysis.go index 9b9d5e0ad..a15b9db5f 100644 --- a/models/user_business_analysis.go +++ b/models/user_business_analysis.go @@ -1,7 +1,6 @@ package models import ( - "encoding/json" "fmt" "sort" "strconv" @@ -202,15 +201,7 @@ func QueryUserStaticDataAll(opts *UserBusinessAnalysisQueryOptions) ([]*UserBusi return nil, 0 } log.Info("query return total:" + fmt.Sprint(allCount)) - if allCount == 0 { - CommitCodeSizeMap, err := GetAllUserKPIStats() - if err != nil { - log.Info("query commit code errr.") - } else { - log.Info("query commit code size, len=" + fmt.Sprint(len(CommitCodeSizeMap))) - } - RefreshUserStaticAllTabel(make(map[string]int), CommitCodeSizeMap) - } + pageSize := 1000 totalPage := int(allCount) / pageSize userBusinessAnalysisReturnList := UserBusinessAnalysisAllList{} @@ -370,7 +361,7 @@ func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap ma CodeMergeCountMap := queryPullRequest(start_unix, end_unix) CommitCountMap := queryCommitAction(start_unix, end_unix, 5) - IssueCountMap := queryAction(start_unix, end_unix, 6) + IssueCountMap := queryCreateIssue(start_unix, end_unix) CommentCountMap := queryComment(start_unix, end_unix) FocusRepoCountMap := queryWatch(start_unix, end_unix) @@ -395,7 +386,7 @@ func RefreshUserStaticAllTabel(wikiCountMap map[string]int, CommitCodeSizeMap ma var indexTotal int64 indexTotal = 0 for { - sess.Select("`user`.*").Table("user").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) userList := make([]*User, 0) sess.Find(&userList) for i, userRecord := range userList { @@ -528,7 +519,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, DataDate := startTime.Format("2006-01-02") CodeMergeCountMap := queryPullRequest(start_unix, end_unix) CommitCountMap := queryCommitAction(start_unix, end_unix, 5) - IssueCountMap := queryAction(start_unix, end_unix, 6) + IssueCountMap := queryCreateIssue(start_unix, end_unix) CommentCountMap := queryComment(start_unix, end_unix) FocusRepoCountMap := queryWatch(start_unix, end_unix) @@ -559,7 +550,7 @@ func CounDataByDateAndReCount(wikiCountMap map[string]int, startTime time.Time, var indexTotal int64 indexTotal = 0 for { - sess.Select("`user`.*").Table("user").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("`user`.*").Table("user").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) userList := make([]*User, 0) sess.Find(&userList) @@ -709,7 +700,7 @@ func querySolveIssue(start_unix int64, end_unix int64) map[int64]int { issueAssigneesList := make([]*IssueAssignees, 0) sess.Select("issue_assignees.*").Table("issue_assignees"). Join("inner", "issue", "issue.id=issue_assignees.issue_id"). - Where(cond).Limit(Page_SIZE, int(indexTotal)) + Where(cond).OrderBy("issue_assignees.id asc").Limit(Page_SIZE, int(indexTotal)) sess.Find(&issueAssigneesList) @@ -744,7 +735,7 @@ func queryPullRequest(start_unix int64, end_unix int64) map[int64]int { indexTotal = 0 for { issueList := make([]*Issue, 0) - sess.Select("issue.*").Table("issue").Join("inner", "pull_request", "issue.id=pull_request.issue_id").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("issue.*").Table("issue").Join("inner", "pull_request", "issue.id=pull_request.issue_id").Where(cond).OrderBy("issue.id asc").Limit(Page_SIZE, int(indexTotal)) sess.Find(&issueList) log.Info("query issue(PR) size=" + fmt.Sprint(len(issueList))) for _, issueRecord := range issueList { @@ -777,7 +768,7 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[i var indexTotal int64 indexTotal = 0 for { - sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) actionList := make([]*Action, 0) sess.Find(&actionList) @@ -799,29 +790,30 @@ func queryCommitAction(start_unix int64, end_unix int64, actionType int64) map[i return resultMap } -func queryAction(start_unix int64, end_unix int64, actionType int64) map[int64]int { +func queryCreateIssue(start_unix int64, end_unix int64) map[int64]int { + sess := x.NewSession() defer sess.Close() resultMap := make(map[int64]int) - cond := "op_type=" + fmt.Sprint(actionType) + " and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) + cond := "is_pull=false and created_unix>=" + fmt.Sprint(start_unix) + " and created_unix<=" + fmt.Sprint(end_unix) - count, err := sess.Where(cond).Count(new(Action)) + count, err := sess.Where(cond).Count(new(Issue)) if err != nil { - log.Info("query Action error. return.") + log.Info("query Issue error. return.") return resultMap } var indexTotal int64 indexTotal = 0 for { - sess.Select("id,user_id,op_type,act_user_id").Table("action").Where(cond).Limit(Page_SIZE, int(indexTotal)) - actionList := make([]*Action, 0) - sess.Find(&actionList) - log.Info("query action size=" + fmt.Sprint(len(actionList))) - for _, actionRecord := range actionList { - if _, ok := resultMap[actionRecord.UserID]; !ok { - resultMap[actionRecord.UserID] = 1 + sess.Select("id,poster_id").Table("issue").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) + issueList := make([]*Issue, 0) + sess.Find(&issueList) + log.Info("query issue size=" + fmt.Sprint(len(issueList))) + for _, issueRecord := range issueList { + if _, ok := resultMap[issueRecord.PosterID]; !ok { + resultMap[issueRecord.PosterID] = 1 } else { - resultMap[actionRecord.UserID] += 1 + resultMap[issueRecord.PosterID] += 1 } } indexTotal += Page_SIZE @@ -830,6 +822,7 @@ func queryAction(start_unix int64, end_unix int64, actionType int64) map[int64]i } } return resultMap + } func queryComment(start_unix int64, end_unix int64) map[int64]int { @@ -846,7 +839,7 @@ func queryComment(start_unix int64, end_unix int64) map[int64]int { var indexTotal int64 indexTotal = 0 for { - sess.Select("id,type,poster_id").Table("comment").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,type,poster_id").Table("comment").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) commentList := make([]*Comment, 0) sess.Find(&commentList) log.Info("query Comment size=" + fmt.Sprint(len(commentList))) @@ -882,7 +875,7 @@ func queryWatch(start_unix int64, end_unix int64) map[int64]int { indexTotal = 0 for { watchList := make([]*Watch, 0) - sess.Select("id,user_id,repo_id").Table("watch").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,user_id,repo_id").Table("watch").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) sess.Find(&watchList) log.Info("query Watch size=" + fmt.Sprint(len(watchList))) @@ -920,7 +913,7 @@ func queryStar(start_unix int64, end_unix int64) map[int64]int { var indexTotal int64 indexTotal = 0 for { - sess.Select("id,uid,repo_id").Table("star").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,uid,repo_id").Table("star").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) starList := make([]*Star, 0) sess.Find(&starList) @@ -956,7 +949,7 @@ func queryFollow(start_unix int64, end_unix int64) map[int64]int { var indexTotal int64 indexTotal = 0 for { - sess.Select("id,user_id,follow_id").Table("follow").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,user_id,follow_id").Table("follow").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) followList := make([]*Follow, 0) sess.Find(&followList) @@ -992,7 +985,7 @@ func queryDatasetSize(start_unix int64, end_unix int64) map[int64]int { var indexTotal int64 indexTotal = 0 for { - sess.Select("id,uploader_id,size").Table("attachment").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,uploader_id,size").Table("attachment").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) attachmentList := make([]*Attachment, 0) sess.Find(&attachmentList) @@ -1028,7 +1021,7 @@ func queryUserCreateRepo(start_unix int64, end_unix int64) map[int64]int { var indexTotal int64 indexTotal = 0 for { - sess.Select("id,owner_id,name").Table("repository").Where(cond).Limit(Page_SIZE, int(indexTotal)) + sess.Select("id,owner_id,name").Table("repository").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) repoList := make([]*Repository, 0) sess.Find(&repoList) log.Info("query Repository size=" + fmt.Sprint(len(repoList))) @@ -1099,8 +1092,7 @@ func queryUserRepoOpenIIndex(start_unix int64, end_unix int64) map[int64]float64 } } - userMapJson, _ := json.Marshal(userMap) - log.Info("userMapJson=" + string(userMapJson)) + log.Info("user openi index size=" + fmt.Sprint(len(userMap))) return userMap } @@ -1119,7 +1111,7 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { var indexTotal int64 indexTotal = 0 for { - statictisSess.Select("id,u_id").Table("user_login_log").Where(cond).Limit(Page_SIZE, int(indexTotal)) + statictisSess.Select("id,u_id").Table("user_login_log").Where(cond).OrderBy("id asc").Limit(Page_SIZE, int(indexTotal)) userLoginLogList := make([]*UserLoginLog, 0) statictisSess.Find(&userLoginLogList) log.Info("query user login size=" + fmt.Sprint(len(userLoginLogList))) @@ -1135,7 +1127,7 @@ func queryLoginCount(start_unix int64, end_unix int64) map[int64]int { break } } - + log.Info("user login size=" + fmt.Sprint(len(resultMap))) return resultMap } diff --git a/modules/auth/org.go b/modules/auth/org.go index 20e2b0999..9642e1ce6 100644 --- a/modules/auth/org.go +++ b/modules/auth/org.go @@ -70,3 +70,7 @@ type CreateTeamForm struct { func (f *CreateTeamForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors { return validate(errs, ctx.Data, f, ctx.Locale) } + +type SubmitReposOfTagForm struct { + RepoList []int64 +} diff --git a/modules/cloudbrain/cloudbrain.go b/modules/cloudbrain/cloudbrain.go index 0f1c700d2..b8aa2e143 100755 --- a/modules/cloudbrain/cloudbrain.go +++ b/modules/cloudbrain/cloudbrain.go @@ -1,6 +1,8 @@ package cloudbrain import ( + "code.gitea.io/gitea/modules/storage" + "encoding/json" "errors" "strconv" @@ -107,6 +109,9 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, uuid var resourceSpec *models.ResourceSpec + if ResourceSpecs == nil { + json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) + } for _, spec := range ResourceSpecs.ResourceSpec { if resourceSpecId == spec.Id { resourceSpec = spec @@ -185,28 +190,143 @@ func GenerateTask(ctx *context.Context, jobName, image, command, uuid, codePath, }, }) if err != nil { - log.Error("CreateJob failed:", err.Error()) + log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"]) return err } if jobResult.Code != Success { - log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg) + log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"]) return errors.New(jobResult.Msg) } var jobID = jobResult.Payload["jobId"].(string) err = models.CreateCloudbrain(&models.Cloudbrain{ - Status: string(models.JobWaiting), - UserID: ctx.User.ID, - RepoID: ctx.Repo.Repository.ID, - JobID: jobID, - JobName: jobName, - SubTaskName: SubTaskName, - JobType: jobType, - Type: models.TypeCloudBrainOne, - Uuid: uuid, + Status: string(models.JobWaiting), + UserID: ctx.User.ID, + RepoID: ctx.Repo.Repository.ID, + JobID: jobID, + JobName: jobName, + SubTaskName: SubTaskName, + JobType: jobType, + Type: models.TypeCloudBrainOne, + Uuid: uuid, + Image: image, + GpuQueue: gpuQueue, + ResourceSpecId: resourceSpecId, + ComputeResource: models.GPUResource, + }) + + if err != nil { + return err + } + + return nil +} + +func RestartTask(ctx *context.Context, task *models.Cloudbrain) error { + dataActualPath := setting.Attachment.Minio.RealPath + + setting.Attachment.Minio.Bucket + "/" + + setting.Attachment.Minio.BasePath + + models.AttachmentRelativePath(task.Uuid) + + task.Uuid + jobName := task.JobName + + var resourceSpec *models.ResourceSpec + if ResourceSpecs == nil { + json.Unmarshal([]byte(setting.ResourceSpecs), &ResourceSpecs) + } + for _, spec := range ResourceSpecs.ResourceSpec { + if task.ResourceSpecId == spec.Id { + resourceSpec = spec + } + } + + if resourceSpec == nil { + log.Error("no such resourceSpecId(%d)", task.ResourceSpecId, ctx.Data["MsgID"]) + return errors.New("no such resourceSpec") + } + + jobResult, err := CreateJob(jobName, models.CreateJobParams{ + JobName: jobName, + RetryCount: 1, + GpuType: task.GpuQueue, + Image: task.Image, + TaskRoles: []models.TaskRole{ + { + Name: SubTaskName, + TaskNumber: 1, + MinSucceededTaskCount: 1, + MinFailedTaskCount: 1, + CPUNumber: resourceSpec.CpuNum, + GPUNumber: resourceSpec.GpuNum, + MemoryMB: resourceSpec.MemMiB, + ShmMB: resourceSpec.ShareMemMiB, + Command: Command, + NeedIBDevice: false, + IsMainRole: false, + UseNNI: false, + }, + }, + Volumes: []models.Volume{ + { + HostPath: models.StHostPath{ + Path: storage.GetMinioPath(jobName, CodeMountPath + "/"), + MountPath: CodeMountPath, + ReadOnly: false, + }, + }, + { + HostPath: models.StHostPath{ + Path: dataActualPath, + MountPath: DataSetMountPath, + ReadOnly: true, + }, + }, + { + HostPath: models.StHostPath{ + Path: storage.GetMinioPath(jobName, ModelMountPath + "/"), + MountPath: ModelMountPath, + ReadOnly: false, + }, + }, + { + HostPath: models.StHostPath{ + Path: storage.GetMinioPath(jobName, BenchMarkMountPath + "/"), + MountPath: BenchMarkMountPath, + ReadOnly: true, + }, + }, + { + HostPath: models.StHostPath{ + Path: storage.GetMinioPath(jobName, Snn4imagenetMountPath + "/"), + MountPath: Snn4imagenetMountPath, + ReadOnly: true, + }, + }, + { + HostPath: models.StHostPath{ + Path: storage.GetMinioPath(jobName, BrainScoreMountPath + "/"), + MountPath: BrainScoreMountPath, + ReadOnly: true, + }, + }, + }, }) + if err != nil { + log.Error("CreateJob failed:", err.Error(), ctx.Data["MsgID"]) + return err + } + if jobResult.Code != Success { + log.Error("CreateJob(%s) failed:%s", jobName, jobResult.Msg, ctx.Data["MsgID"]) + return errors.New(jobResult.Msg) + } + + var jobID = jobResult.Payload["jobId"].(string) + task.JobID = jobID + task.Status = string(models.JobWaiting) + err = models.UpdateJob(task) if err != nil { + log.Error("UpdateJob(%s) failed:%v", jobName, err.Error(), ctx.Data["MsgID"]) return err } diff --git a/modules/git/repo.go b/modules/git/repo.go index 772f1d149..f72f5df7e 100644 --- a/modules/git/repo.go +++ b/modules/git/repo.go @@ -445,8 +445,12 @@ type Contributor struct { Email string } -func GetContributors(repoPath string) ([]Contributor, error){ - cmd := NewCommand("shortlog", "-sne", "--all") +func GetContributors(repoPath string, branchOrTag ...string) ([]Contributor, error) { + targetBranchOrTag := "HEAD" + if len(branchOrTag) > 0 && branchOrTag[0] != "" { + targetBranchOrTag = branchOrTag[0] + } + cmd := NewCommand("shortlog", "-sne", targetBranchOrTag) stdout, err := cmd.RunInDir(repoPath) if err != nil { return nil, err @@ -462,9 +466,9 @@ func GetContributors(repoPath string) ([]Contributor, error){ } number := oneCount[0:strings.Index(oneCount, "\t")] commitCnt, _ := strconv.Atoi(number) - committer := oneCount[strings.Index(oneCount, "\t")+1:strings.LastIndex(oneCount, " ")] + committer := oneCount[strings.Index(oneCount, "\t")+1 : strings.LastIndex(oneCount, " ")] committer = strings.Trim(committer, " ") - email := oneCount[strings.Index(oneCount, "<")+1:strings.Index(oneCount, ">")] + email := oneCount[strings.Index(oneCount, "<")+1 : strings.Index(oneCount, ">")] contributorsInfo[i] = Contributor{ commitCnt, committer, email, } diff --git a/modules/modelarts/modelarts.go b/modules/modelarts/modelarts.go index 273d59012..06eac1665 100755 --- a/modules/modelarts/modelarts.go +++ b/modules/modelarts/modelarts.go @@ -48,12 +48,8 @@ const ( PerPage = 10 IsLatestVersion = "1" NotLatestVersion = "0" - // ComputeResource = "NPU" - NPUResource = "NPU" - GPUResource = "CPU/GPU" - AllResource = "all" - DebugType = -1 - VersionCount = 1 + DebugType = -1 + VersionCount = 1 SortByCreateTime = "create_time" ConfigTypeCustom = "custom" @@ -215,14 +211,15 @@ func GenerateTask(ctx *context.Context, jobName, uuid, description, flavor strin } err = models.CreateCloudbrain(&models.Cloudbrain{ - Status: string(models.JobWaiting), - UserID: ctx.User.ID, - RepoID: ctx.Repo.Repository.ID, - JobID: jobResult.ID, - JobName: jobName, - JobType: string(models.JobTypeDebug), - Type: models.TypeCloudBrainTwo, - Uuid: uuid, + Status: string(models.JobWaiting), + UserID: ctx.User.ID, + RepoID: ctx.Repo.Repository.ID, + JobID: jobResult.ID, + JobName: jobName, + JobType: string(models.JobTypeDebug), + Type: models.TypeCloudBrainTwo, + Uuid: uuid, + ComputeResource: models.NPUResource, }) if err != nil { @@ -277,7 +274,7 @@ func GenerateTrainJob(ctx *context.Context, req *GenerateTrainJobReq) (err error DatasetName: attach.Name, CommitID: req.CommitID, IsLatestVersion: req.IsLatestVersion, - ComputeResource: NPUResource, + ComputeResource: models.NPUResource, EngineID: req.EngineID, TrainUrl: req.TrainUrl, BranchName: req.BranchName, @@ -360,7 +357,7 @@ func GenerateTrainJobVersion(ctx *context.Context, req *GenerateTrainJobReq, job CommitID: req.CommitID, IsLatestVersion: req.IsLatestVersion, PreVersionName: req.PreVersionName, - ComputeResource: NPUResource, + ComputeResource: models.GPUResource, EngineID: req.EngineID, TrainUrl: req.TrainUrl, BranchName: req.BranchName, diff --git a/modules/modelarts/resty.go b/modules/modelarts/resty.go index 2cc9e34be..07f26ceb7 100755 --- a/modules/modelarts/resty.go +++ b/modules/modelarts/resty.go @@ -174,7 +174,7 @@ sendjob: return &result, nil } -func StopJob(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { +func ManageNotebook(jobID string, param models.NotebookAction) (*models.NotebookActionResult, error) { checkSetting() client := getRestyClient() var result models.NotebookActionResult @@ -207,8 +207,8 @@ sendjob: } if len(response.ErrorCode) != 0 { - log.Error("StopJob failed(%s): %s", response.ErrorCode, response.ErrorMsg) - return &result, fmt.Errorf("StopJob failed(%s): %s", response.ErrorCode, response.ErrorMsg) + log.Error("ManageNotebook failed(%s): %s", response.ErrorCode, response.ErrorMsg) + return &result, fmt.Errorf("ManageNotebook failed(%s): %s", response.ErrorCode, response.ErrorMsg) } return &result, nil diff --git a/modules/repository/elk_pagedata.go b/modules/repository/elk_pagedata.go index 1454f0364..ecdbff078 100644 --- a/modules/repository/elk_pagedata.go +++ b/modules/repository/elk_pagedata.go @@ -21,7 +21,8 @@ type Fields struct { Format string `json:"format"` } type MatchPhrase struct { - Message string `json:"message"` + Message string `json:"message,omitempty"` + TagName string `json:"tagName.keyword,omitempty"` } type Should struct { MatchPhrase MatchPhrase `json:"match_phrase"` @@ -144,7 +145,7 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje inputStruct.Batch[0].Request.Params.Body.Fields = make([]Fields, 1) inputStruct.Batch[0].Request.Params.Body.Fields[0].Field = setting.TimeField inputStruct.Batch[0].Request.Params.Body.Fields[0].Format = setting.ElkTimeFormat - inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 3) + inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter = make([]Filter, 4) //限定查询时间 var timeRange Range timeRange.Timestamptest.Gte = Gte @@ -159,6 +160,24 @@ func ProjectViewInit(User string, Project string, Gte string, Lte string) (proje var projectName FilterMatchPhrase projectName.ProjectName = Project inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[2].FilterMatchPhrase = &projectName + //限定页面 + var bool Bool + bool.Should = make([]Should, 14) + bool.Should[0].MatchPhrase.TagName = "%{[request][3]}" + bool.Should[1].MatchPhrase.TagName = "datasets?type=0" + bool.Should[2].MatchPhrase.TagName = "datasets?type=1" + bool.Should[3].MatchPhrase.TagName = "issues" + bool.Should[4].MatchPhrase.TagName = "labels" + bool.Should[5].MatchPhrase.TagName = "pulls" + bool.Should[6].MatchPhrase.TagName = "wiki" + bool.Should[7].MatchPhrase.TagName = "activity" + bool.Should[8].MatchPhrase.TagName = "cloudbrain" + bool.Should[9].MatchPhrase.TagName = "modelarts" + bool.Should[10].MatchPhrase.TagName = "blockchain" + bool.Should[11].MatchPhrase.TagName = "watchers" + bool.Should[12].MatchPhrase.TagName = "stars" + bool.Should[13].MatchPhrase.TagName = "forks" + inputStruct.Batch[0].Request.Params.Body.Query.BoolIn.Filter[3].Bool = &bool return inputStruct } diff --git a/modules/storage/local.go b/modules/storage/local.go old mode 100644 new mode 100755 index d46a5528d..df5807f87 --- a/modules/storage/local.go +++ b/modules/storage/local.go @@ -80,3 +80,7 @@ func (l *LocalStorage) HasObject(path string) (bool, error) { func (l *LocalStorage) UploadObject(fileName, filePath string) error { return nil } + +func (l *LocalStorage) DeleteDir(dir string) error { + return nil +} diff --git a/modules/storage/minio.go b/modules/storage/minio.go index 664e58d1b..c6f704df5 100755 --- a/modules/storage/minio.go +++ b/modules/storage/minio.go @@ -11,6 +11,9 @@ import ( "strings" "time" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/modules/setting" + "github.com/minio/minio-go" ) @@ -76,6 +79,29 @@ func (m *MinioStorage) Delete(path string) error { return m.client.RemoveObject(m.bucket, m.buildMinioPath(path)) } +// Delete delete a file +func (m *MinioStorage) DeleteDir(dir string) error { + objectsCh := make(chan string) + + // Send object names that are needed to be removed to objectsCh + go func() { + defer close(objectsCh) + // List all objects from a bucket-name with a matching prefix. + for object := range m.client.ListObjects(m.bucket, dir, true, nil) { + if object.Err != nil { + log.Error("ListObjects failed:%v", object.Err) + } + objectsCh <- object.Key + } + }() + + for rErr := range m.client.RemoveObjects(m.bucket, objectsCh) { + log.Error("Error detected during deletion: ", rErr) + } + + return nil +} + //Get Presigned URL for get object func (m *MinioStorage) PresignedGetURL(path string, fileName string) (string, error) { // Set request parameters for content-disposition. @@ -128,3 +154,7 @@ func (m *MinioStorage) UploadObject(fileName, filePath string) error { _, err := m.client.FPutObject(m.bucket, fileName, filePath, minio.PutObjectOptions{}) return err } + +func GetMinioPath(jobName, suffixPath string) string { + return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath +} diff --git a/modules/storage/storage.go b/modules/storage/storage.go index d364346f0..fc9d38020 100755 --- a/modules/storage/storage.go +++ b/modules/storage/storage.go @@ -23,6 +23,7 @@ type ObjectStorage interface { Save(path string, r io.Reader) (int64, error) Open(path string) (io.ReadCloser, error) Delete(path string) error + DeleteDir(dir string) error PresignedGetURL(path string, fileName string) (string, error) PresignedPutURL(path string) (string, error) HasObject(path string) (bool, error) diff --git a/options/locale/locale_en-US.ini b/options/locale/locale_en-US.ini index d58a61756..35f0a98bf 100644 --- a/options/locale/locale_en-US.ini +++ b/options/locale/locale_en-US.ini @@ -222,6 +222,7 @@ contributors = Contributors [explore] repos = Repositories +select_repos = Select the project users = Users organizations = Organizations images = CloudImages @@ -234,6 +235,8 @@ org_no_results = No matching organizations found. code_no_results = No source code matching your search term found. code_search_results = Search results for '%s' code_last_indexed_at = Last indexed %s +save=save +cancel=cancel [auth] create_new_account = Register Account @@ -778,6 +781,10 @@ datasets = Datasets datasets.desc = Enable Dataset cloudbrain_helper=Use GPU/NPU resources to open notebooks, model training tasks, etc. +model_manager = Model +model_noright=No right +model_rename=Duplicate model name, please modify model name. + debug=Debug stop=Stop delete=Delete @@ -896,6 +903,8 @@ model.manage.F1 = F1 model.manage.Precision = Precision model.manage.Recall = Recall model.manage.sava_model = Sava Model +model.manage.model_manage = ModelManage +model.manage.model_accuracy = Model Accuracy template.items = Template Items template.git_content = Git Content (Default Branch) @@ -1127,6 +1136,7 @@ issues.filter_label_exclude = `Use alt + click/enter t issues.filter_label_no_select = All labels issues.filter_milestone = Milestone issues.filter_milestone_no_select = All milestones +issues.filter_milestone_no_add = Not add milestones issues.filter_assignee = Assignee issues.filter_assginee_no_select = All assignees issues.filter_type = Type diff --git a/options/locale/locale_zh-CN.ini b/options/locale/locale_zh-CN.ini index 45cabda8f..0389471c2 100755 --- a/options/locale/locale_zh-CN.ini +++ b/options/locale/locale_zh-CN.ini @@ -224,6 +224,7 @@ contributors=贡献者 [explore] repos=项目 +select_repos=精选项目 users=用户 organizations=组织 images = 云脑镜像 @@ -238,6 +239,8 @@ org_no_results=未找到匹配的组织。 code_no_results=未找到与搜索字词匹配的源代码。 code_search_results=“%s” 的搜索结果是 code_last_indexed_at=最后索引于 %s +save=保存 +cancel=取消 [auth] create_new_account=注册帐号 @@ -784,8 +787,10 @@ cloudbrain_helper=使用GPU/NPU资源,开启Notebook、模型训练任务等 model_manager = 模型 model_noright=无权限操作 +model_rename=模型名称重复,请修改模型名称 debug=调试 +debug_again=再次调试 stop=停止 delete=删除 model_download=模型下载 @@ -908,6 +913,8 @@ model.manage.F1 = F1值 model.manage.Precision = 精确率 model.manage.Recall = 召回率 model.manage.sava_model = 保存模型 +model.manage.model_manage = 模型管理 +model.manage.model_accuracy = 模型精度 template.items=模板选项 template.git_content=Git数据(默认分支) @@ -1140,6 +1147,7 @@ issues.filter_label_exclude=`使用 alt + 鼠标左键 / 回 issues.filter_label_no_select=所有标签 issues.filter_milestone=里程碑筛选 issues.filter_milestone_no_select=所有里程碑 +issues.filter_milestone_no_add=未添加里程碑 issues.filter_assignee=指派人筛选 issues.filter_assginee_no_select=所有指派成员 issues.filter_type=类型筛选 diff --git a/package-lock.json b/package-lock.json index d45f8c6f8..a8e5e3e25 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11655,6 +11655,11 @@ "autolinker": "~0.28.0" } }, + "remixicon": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/remixicon/-/remixicon-2.5.0.tgz", + "integrity": "sha512-q54ra2QutYDZpuSnFjmeagmEiN9IMo56/zz5dDNitzKD23oFRw77cWo4TsrAdmdkPiEn8mxlrTqxnkujDbEGww==" + }, "remove-bom-buffer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/remove-bom-buffer/-/remove-bom-buffer-3.0.0.tgz", diff --git a/package.json b/package.json index 7147bea0d..ba5459a07 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "postcss-preset-env": "6.7.0", "postcss-safe-parser": "4.0.2", "qs": "6.9.4", + "remixicon": "2.5.0", "spark-md5": "3.0.1", "svg-sprite-loader": "5.0.0", "svgo": "1.3.2", diff --git a/routers/actionnotification.go b/routers/actionnotification.go new file mode 100644 index 000000000..b3e151c1c --- /dev/null +++ b/routers/actionnotification.go @@ -0,0 +1,53 @@ +package routers + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/log" + "code.gitea.io/gitea/services/socketwrap" + "github.com/gorilla/websocket" +) + +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, +} + +var SocketManager = socketwrap.NewClientsManager() + +func ActionNotification(ctx *context.Context) { + + conn, err := upgrader.Upgrade(ctx.Resp, ctx.Req.Request, nil) + if err != nil { + log.Warn("can not create connection.", err) + return + } + client := &socketwrap.Client{Manager: SocketManager, Conn: conn, Send: make(chan *models.Action, 256)} + + WriteLastTenActionsIfHave(conn) + + client.Manager.Register <- client + + go client.WritePump() + +} + +func WriteLastTenActionsIfHave(conn *websocket.Conn) { + socketwrap.LastTenActionsQueue.Mutex.RLock() + { + size := socketwrap.LastTenActionsQueue.Queue.Len() + if size > 0 { + tempE := socketwrap.LastTenActionsQueue.Queue.Front() + conn.WriteJSON(tempE) + for i := 1; i < size; i++ { + tempE = tempE.Next() + conn.WriteJSON(tempE) + + } + } + + } + socketwrap.LastTenActionsQueue.Mutex.RUnlock() +} + + diff --git a/routers/api/v1/repo/modelarts.go b/routers/api/v1/repo/modelarts.go index a18da3fe5..283696007 100755 --- a/routers/api/v1/repo/modelarts.go +++ b/routers/api/v1/repo/modelarts.go @@ -15,6 +15,7 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/modelarts" "code.gitea.io/gitea/modules/storage" + routerRepo "code.gitea.io/gitea/routers/repo" ) func GetModelArtsNotebook(ctx *context.APIContext) { @@ -237,7 +238,7 @@ func DelTrainJobVersion(ctx *context.APIContext) { JobID: jobID, }) if err != nil { - ctx.ServerError("get VersionListCount faild", err) + ctx.ServerError("get VersionListCount failed", err) return } if VersionListCount > 0 { @@ -255,6 +256,8 @@ func DelTrainJobVersion(ctx *context.APIContext) { return } } + } else { //已删除该任务下的所有版本 + routerRepo.DeleteJobStorage(task.JobName) } ctx.JSON(http.StatusOK, map[string]interface{}{ diff --git a/routers/org/home.go b/routers/org/home.go index b11c179c1..df600d96d 100755 --- a/routers/org/home.go +++ b/routers/org/home.go @@ -130,5 +130,13 @@ func Home(ctx *context.Context) { pager.SetDefaultParams(ctx) ctx.Data["Page"] = pager + //find org tag info + tags, err := models.GetAllOfficialTagRepos(org.ID, ctx.Org.IsOwner) + if err != nil { + ctx.ServerError("GetAllOfficialTagRepos", err) + return + } + + ctx.Data["tags"] = tags ctx.HTML(200, tplOrgHome) } diff --git a/routers/org/tag.go b/routers/org/tag.go new file mode 100644 index 000000000..37d5b1c8f --- /dev/null +++ b/routers/org/tag.go @@ -0,0 +1,90 @@ +// Copyright 2014 The Gogs Authors. All rights reserved. +// Copyright 2020 The Gitea Authors. +// Use of this source code is governed by a MIT-style +// license that can be found in the LICENSE file. + +package org + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/auth" + "code.gitea.io/gitea/modules/context" + "errors" + "strconv" +) + +const DefaultOrgTagLimit = -1 + +// SubmitTags submit repos of org tag +func SubmitTags(ctx *context.Context, form auth.SubmitReposOfTagForm) { + if !ctx.Org.IsOwner { + ctx.ServerError("UpdateTagReposByID", errors.New("no access to submit tags")) + return + } + tag := getTagFromContext(ctx) + if ctx.Written() { + return + } + if tag.Limit != DefaultOrgTagLimit && len(form.RepoList) > tag.Limit { + ctx.ServerError("UpdateTagReposByID", errors.New("tags size over limit")) + return + } + err := models.UpdateTagReposByID(tag.ID, ctx.Org.Organization.ID, form.RepoList) + if err != nil { + ctx.ServerError("UpdateTagReposByID", err) + return + } + + ctx.JSON(200, map[string]interface{}{ + "code": "00", + "msg": "success", + }) +} + +// GetTagRepos get repos under org tag +func GetTagRepos(ctx *context.Context) { + if !ctx.Org.IsOwner { + ctx.ServerError("GetTagRepos", errors.New("no access to get tags")) + return + } + tag := getTagFromContext(ctx) + if ctx.Written() { + return + } + + r, err := models.GetTagRepos(tag.ID, ctx.Org.Organization.ID) + if err != nil { + ctx.ServerError("GetTagRepos", err) + return + } + + ctx.JSON(200, map[string]interface{}{ + "code": "00", + "msg": "success", + "data": r, + }) +} + +// getTagFromContext finds out tag info From context. +func getTagFromContext(ctx *context.Context) *models.OfficialTag { + var tag *models.OfficialTag + var err error + + tagIdStr := ctx.Query("tagId") + if len(tagIdStr) == 0 { + ctx.ServerError("GetTagInfo", errors.New("tag is not exist")) + return nil + } + tagId, _ := strconv.ParseInt(tagIdStr, 10, 32) + tag, err = models.GetTagByID(tagId) + if err != nil { + if models.IsErrTagNotExist(err) { + ctx.NotFound("GetTagInfo", err) + } else { + ctx.ServerError("GetTagInfo", err) + } + return nil + } + + return tag +} diff --git a/routers/repo/ai_model_manage.go b/routers/repo/ai_model_manage.go index ad68f5b99..669bdf9fa 100644 --- a/routers/repo/ai_model_manage.go +++ b/routers/repo/ai_model_manage.go @@ -105,6 +105,23 @@ func saveModelByParameters(jobId string, versionName string, name string, versio return nil } +func SaveNewNameModel(ctx *context.Context) { + name := ctx.Query("Name") + if name == "" { + ctx.Error(500, fmt.Sprintf("name or version is null.")) + return + } + + aimodels := models.QueryModelByName(name, ctx.Repo.Repository.ID) + if len(aimodels) > 0 { + ctx.Error(500, ctx.Tr("repo.model_rename")) + return + } + SaveModel(ctx) + + log.Info("save model end.") +} + func SaveModel(ctx *context.Context) { log.Info("save model start.") JobId := ctx.Query("JobId") diff --git a/routers/repo/blockchain.go b/routers/repo/blockchain.go index dc3fcd848..6bd546ce6 100755 --- a/routers/repo/blockchain.go +++ b/routers/repo/blockchain.go @@ -72,7 +72,7 @@ func HandleBlockChainInitNotify(ctx *context.Context) { repo.BlockChainStatus = models.RepoBlockChainSuccess repo.ContractAddress = req.ContractAddress - if err = models.UpdateRepositoryCols(repo, "block_chain_status", "contract_address"); err != nil { + if err = repo.UpdateBlockChain(); err != nil { log.Error("UpdateRepositoryCols failed:%v", err.Error(), ctx.Data["msgID"]) ctx.JSON(200, map[string]string{ "code": "-1", diff --git a/routers/repo/cloudbrain.go b/routers/repo/cloudbrain.go index 3f5fce013..ab3303408 100755 --- a/routers/repo/cloudbrain.go +++ b/routers/repo/cloudbrain.go @@ -206,7 +206,7 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { } repo := ctx.Repo.Repository downloadCode(repo, codePath) - uploadCodeToMinio(codePath+"/", jobName, "/code/") + uploadCodeToMinio(codePath+"/", jobName, cloudbrain.CodeMountPath+"/") modelPath := setting.JobPath + jobName + cloudbrain.ModelMountPath + "/" mkModelPath(modelPath) @@ -236,15 +236,89 @@ func CloudBrainCreate(ctx *context.Context, form auth.CreateCloudBrainForm) { uploadCodeToMinio(brainScorePath+"/", jobName, cloudbrain.BrainScoreMountPath+"/") } - err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, codePath, getMinioPath(jobName, cloudbrain.ModelMountPath+"/"), - getMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), getMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), - getMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, resourceSpecId) + err = cloudbrain.GenerateTask(ctx, jobName, image, command, uuid, storage.GetMinioPath(jobName, cloudbrain.CodeMountPath+"/"), + storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/"), + storage.GetMinioPath(jobName, cloudbrain.BenchMarkMountPath+"/"), storage.GetMinioPath(jobName, cloudbrain.Snn4imagenetMountPath+"/"), + storage.GetMinioPath(jobName, cloudbrain.BrainScoreMountPath+"/"), jobType, gpuQueue, resourceSpecId) if err != nil { cloudBrainNewDataPrepare(ctx) ctx.RenderWithErr(err.Error(), tplCloudBrainNew, &form) return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") +} + +func CloudBrainRestart(ctx *context.Context) { + var jobID = ctx.Params(":jobid") + var resultCode = "0" + var errorMsg = "" + var status = "" + + for { + task, err := models.GetCloudbrainByJobID(jobID) + if err != nil { + log.Error("GetCloudbrainByJobID(%s) failed:%v", jobID, err.Error(), ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } + + if task.Status != string(models.JobStopped) && task.Status != string(models.JobSucceeded) && task.Status != string(models.JobFailed) { + log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "the job is not stopped" + break + } + + if task.Image == "" || task.GpuQueue == "" || task.Type != models.TypeCloudBrainOne { + log.Error("the job(%s) version is too old", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "the job's version is too old and can not be restarted" + break + } + + if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()){ + log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "you have no right to restart the job" + break + } + + count, err := models.GetCloudbrainCountByUserID(ctx.User.ID) + if err != nil { + log.Error("GetCloudbrainCountByUserID failed:%v", err, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } else { + if count >= 1 { + log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "you have already a running or waiting task, can not create more" + break + } + } + + err = cloudbrain.RestartTask(ctx, task) + if err != nil { + log.Error("RestartTask failed:%v", err.Error(), ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } + + status = task.Status + jobID = task.JobID + + break + } + + ctx.JSON(200, map[string]string{ + "result_code": resultCode, + "error_msg": errorMsg, + "status": status, + "job_id": jobID, + }) } func CloudBrainShow(ctx *context.Context) { @@ -351,32 +425,53 @@ func CloudBrainCommitImage(ctx *context.Context, form auth.CommitImageCloudBrain func CloudBrainStop(ctx *context.Context) { var jobID = ctx.Params(":jobid") - task, err := models.GetCloudbrainByJobID(jobID) - if err != nil { - ctx.ServerError("GetCloudbrainByJobID failed", err) - return - } + var resultCode = "0" + var errorMsg = "" + var status = "" - if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) { - log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) - ctx.ServerError("the job has been stopped", errors.New("the job has been stopped")) - return - } + for { + task, err := models.GetCloudbrainByJobID(jobID) + if err != nil { + log.Error("GetCloudbrainByJobID(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } - err = cloudbrain.StopJob(jobID) - if err != nil { - log.Error("StopJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["msgID"]) - ctx.ServerError("StopJob failed", err) - return - } + if task.Status == string(models.JobStopped) || task.Status == string(models.JobFailed) { + log.Error("the job(%s) has been stopped", task.JobName, ctx.Data["msgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } - task.Status = string(models.JobStopped) - err = models.UpdateJob(task) - if err != nil { - ctx.ServerError("UpdateJob failed", err) - return + err = cloudbrain.StopJob(jobID) + if err != nil { + log.Error("StopJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } + + task.Status = string(models.JobStopped) + err = models.UpdateJob(task) + if err != nil { + log.Error("UpdateJob(%s) failed:%v", task.JobName, err, ctx.Data["msgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } + + status = task.Status + break } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") + + ctx.JSON(200, map[string]string{ + "result_code": resultCode, + "error_msg": errorMsg, + "status": status, + "job_id": jobID, + }) } func StopJobsByUserID(userID int64) { @@ -423,7 +518,7 @@ func StopJobs(cloudBrains []*models.Cloudbrain) { Action: models.ActionStop, } err := retry(3, time.Second*30, func() error { - _, err := modelarts.StopJob(taskInfo.JobID, param) + _, err := modelarts.ManageNotebook(taskInfo.JobID, param) return err }) logErrorAndUpdateJobStatus(err, taskInfo) @@ -478,7 +573,9 @@ func CloudBrainDel(ctx *context.Context) { ctx.ServerError("DeleteJob failed", err) return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") + + deleteJobStorage(task.JobName, models.TypeCloudBrainOne) + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") } func CloudBrainShowModels(ctx *context.Context) { @@ -560,7 +657,7 @@ func getImages(ctx *context.Context, imageType string) { func GetModelDirs(jobName string, parentDir string) (string, error) { var req string - modelActualPath := getMinioPath(jobName, cloudbrain.ModelMountPath+"/") + modelActualPath := storage.GetMinioPath(jobName, cloudbrain.ModelMountPath+"/") if parentDir == "" { req = "baseDir=" + modelActualPath } else { @@ -570,10 +667,6 @@ func GetModelDirs(jobName string, parentDir string) (string, error) { return getDirs(req) } -func getMinioPath(jobName, suffixPath string) string { - return setting.Attachment.Minio.RealPath + setting.Attachment.Minio.Bucket + "/" + setting.CBCodePathPrefix + jobName + suffixPath -} - func CloudBrainDownloadModel(ctx *context.Context) { parentDir := ctx.Query("parentDir") fileName := ctx.Query("fileName") @@ -756,6 +849,35 @@ func mkModelPath(modelPath string) error { return nil } +func deleteJobStorage(jobName string, cloudbrainType int) error { + //delete local + localJobPath := setting.JobPath + jobName + err := os.RemoveAll(localJobPath) + if err != nil { + log.Error("RemoveAll(%s) failed:%v", localJobPath, err) + } + + //delete oss + if cloudbrainType == models.TypeCloudBrainOne { + dirPath := setting.CBCodePathPrefix + jobName + "/" + err = storage.Attachments.DeleteDir(dirPath) + if err != nil { + log.Error("DeleteDir(%s) failed:%v", localJobPath, err) + } + } else if cloudbrainType == models.TypeCloudBrainTwo { + //dirPath := setting.CodePathPrefix + jobName + "/" + //err = storage.ObsRemoveObject(setting.Bucket, dirPath) + //if err != nil { + // log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) + //} + log.Info("no need to delete") + } else { + log.Error("cloudbrainType(%d) error", cloudbrainType) + } + + return nil +} + func SyncCloudbrainStatus() { cloudBrains, err := models.GetCloudBrainUnStoppedJob() if err != nil { diff --git a/routers/repo/issue.go b/routers/repo/issue.go index 77ed0251d..7ab5eb283 100755 --- a/routers/repo/issue.go +++ b/routers/repo/issue.go @@ -193,6 +193,8 @@ func issues(ctx *context.Context, milestoneID int64, isPullOption util.OptionalB var mileIDs []int64 if milestoneID > 0 { mileIDs = []int64{milestoneID} + } else if milestoneID == -1 { //only search no milestone + mileIDs = []int64{0} } var issues []*models.Issue @@ -355,7 +357,8 @@ func Issues(ctx *context.Context) { var err error // Get milestones. - ctx.Data["Milestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateType(ctx.Query("state")), models.ListOptions{}) + ctx.Data["OpenMilestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateOpen, models.ListOptions{}) + ctx.Data["ClosedMilestones"], err = models.GetMilestonesByRepoID(ctx.Repo.Repository.ID, api.StateClosed, models.ListOptions{}) if err != nil { ctx.ServerError("GetAllRepoMilestones", err) return diff --git a/routers/repo/milestone.go b/routers/repo/milestone.go index e30e6371f..41f1f88bc 100644 --- a/routers/repo/milestone.go +++ b/routers/repo/milestone.go @@ -268,6 +268,7 @@ func MilestoneIssuesAndPulls(ctx *context.Context) { ctx.Data["CanWriteIssues"] = ctx.Repo.CanWriteIssuesOrPulls(false) ctx.Data["CanWritePulls"] = ctx.Repo.CanWriteIssuesOrPulls(true) + ctx.Data["PageIsIssueList"] = true ctx.HTML(200, tplMilestoneIssues) } diff --git a/routers/repo/modelarts.go b/routers/repo/modelarts.go index d2a094bc8..a907aca01 100755 --- a/routers/repo/modelarts.go +++ b/routers/repo/modelarts.go @@ -11,11 +11,10 @@ import ( "strings" "time" - "code.gitea.io/gitea/modules/cloudbrain" - "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/cloudbrain" "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/log" @@ -42,6 +41,7 @@ const ( func DebugJobIndex(ctx *context.Context) { debugListType := ctx.Query("debugListType") + ctx.Data["ListType"] = debugListType MustEnableCloudbrain(ctx) repo := ctx.Repo.Repository page := ctx.QueryInt("page") @@ -49,12 +49,9 @@ func DebugJobIndex(ctx *context.Context) { page = 1 } debugType := modelarts.DebugType - jobType := string(models.JobTypeDebug) - if debugListType == modelarts.GPUResource { + if debugListType == models.GPUResource { debugType = models.TypeCloudBrainOne - jobType = "" - } - if debugListType == modelarts.NPUResource { + } else if debugListType == models.NPUResource { debugType = models.TypeCloudBrainTwo } @@ -63,9 +60,10 @@ func DebugJobIndex(ctx *context.Context) { Page: page, PageSize: setting.UI.IssuePagingNum, }, - RepoID: repo.ID, - Type: debugType, - JobType: jobType, + RepoID: repo.ID, + Type: debugType, + JobTypeNot: true, + JobType: string(models.JobTypeTrain), }) if err != nil { ctx.ServerError("Get debugjob faild:", err) @@ -73,21 +71,13 @@ func DebugJobIndex(ctx *context.Context) { } for i, task := range ciTasks { - if task.Cloudbrain.Type == models.TypeCloudBrainOne { - ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) - ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) - ciTasks[i].Cloudbrain.ComputeResource = modelarts.GPUResource - } - if task.Cloudbrain.Type == models.TypeCloudBrainTwo { - ciTasks[i].CanDebug = cloudbrain.CanCreateOrDebugJob(ctx) - ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) - ciTasks[i].Cloudbrain.ComputeResource = modelarts.NPUResource - } - + ciTasks[i].CanDebug = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) + ciTasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) + ciTasks[i].Cloudbrain.ComputeResource = task.ComputeResource } pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) - pager.SetDefaultParams(ctx) + pager.AddParam(ctx, "debugListType", "ListType") ctx.Data["Page"] = pager ctx.Data["PageIsCloudBrain"] = true ctx.Data["Tasks"] = ciTasks @@ -156,7 +146,7 @@ func NotebookCreate(ctx *context.Context, form auth.CreateModelArtsNotebookForm) ctx.RenderWithErr(err.Error(), tplModelArtsNotebookNew, &form) return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") } func NotebookShow(ctx *context.Context) { @@ -232,38 +222,105 @@ func NotebookDebug(ctx *context.Context) { ctx.Redirect(debugUrl) } -func NotebookStop(ctx *context.Context) { +func NotebookManage(ctx *context.Context) { var jobID = ctx.Params(":jobid") - log.Info(jobID) - task, err := models.GetCloudbrainByJobID(jobID) - if err != nil { - ctx.ServerError("GetCloudbrainByJobID failed", err) - return - } + var action = ctx.Params(":action") + var resultCode = "0" + var errorMsg = "" + var status = "" - if task.Status != string(models.JobRunning) { - log.Error("the job(%s) is not running", task.JobName) - ctx.ServerError("the job is not running", errors.New("the job is not running")) - return - } + for { + task, err := models.GetCloudbrainByJobID(jobID) + if err != nil { + log.Error("GetCloudbrainByJobID failed:%v", err, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } - param := models.NotebookAction{ - Action: models.ActionStop, - } - res, err := modelarts.StopJob(jobID, param) - if err != nil { - log.Error("StopJob(%s) failed:%v", task.JobName, err.Error()) - ctx.ServerError("StopJob failed", err) - return - } + if action == models.ActionStop { + if task.Status != string(models.ModelArtsRunning) { + log.Error("the job(%s) is not running", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "the job is not running" + break + } - task.Status = res.CurrentStatus - err = models.UpdateJob(task) - if err != nil { - ctx.ServerError("UpdateJob failed", err) - return + if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin() && !ctx.IsUserRepoOwner()) { + log.Error("the user has no right ro stop the job", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "you have no right to stop the job" + break + } + } else if action == models.ActionRestart { + if task.Status != string(models.ModelArtsStopped) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsCreateFailed) { + log.Error("the job(%s) is not stopped", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "the job is not stopped" + break + } + + if !ctx.IsSigned || (ctx.User.ID != task.UserID && !ctx.IsUserSiteAdmin()) { + log.Error("the user has no right ro restart the job", task.JobName, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "you have no right to restart the job" + break + } + + count, err := models.GetCloudbrainNotebookCountByUserID(ctx.User.ID) + if err != nil { + log.Error("GetCloudbrainNotebookCountByUserID failed:%v", err, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } else { + if count >= 1 { + log.Error("the user already has running or waiting task", ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "you have already a running or waiting task, can not create more" + break + } + } + + action = models.ActionStart + } else { + log.Error("the action(%s) is illegal", action, ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "非法操作" + break + } + + param := models.NotebookAction{ + Action: action, + } + res, err := modelarts.ManageNotebook(jobID, param) + if err != nil { + log.Error("ManageNotebook(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "启动失败" + break + } + + task.Status = res.CurrentStatus + err = models.UpdateJob(task) + if err != nil { + log.Error("UpdateJob(%s) failed:%v", task.JobName, err.Error(), ctx.Data["MsgID"]) + resultCode = "-1" + errorMsg = "system error" + break + } + + status = task.Status + + break } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") + + ctx.JSON(200, map[string]string{ + "result_code": resultCode, + "error_msg": errorMsg, + "status": status, + "job_id": jobID, + }) } func NotebookDel(ctx *context.Context) { @@ -274,7 +331,7 @@ func NotebookDel(ctx *context.Context) { return } - if task.Status != string(models.JobStopped) { + if task.Status != string(models.ModelArtsCreateFailed) && task.Status != string(models.ModelArtsStartFailed) && task.Status != string(models.ModelArtsStopped) { log.Error("the job(%s) has not been stopped", task.JobName) ctx.ServerError("the job has not been stopped", errors.New("the job has not been stopped")) return @@ -293,7 +350,7 @@ func NotebookDel(ctx *context.Context) { return } - ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob") + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/debugjob?debugListType=all") } func TrainJobIndex(ctx *context.Context) { @@ -312,6 +369,7 @@ func TrainJobIndex(ctx *context.Context) { }, RepoID: repo.ID, Type: models.TypeCloudBrainTwo, + JobTypeNot: false, JobType: string(models.JobTypeTrain), IsLatestVersion: modelarts.IsLatestVersion, }) @@ -323,6 +381,7 @@ func TrainJobIndex(ctx *context.Context) { for i, task := range tasks { tasks[i].CanDel = cloudbrain.CanDeleteJob(ctx, &task.Cloudbrain) tasks[i].CanModify = cloudbrain.CanModifyJob(ctx, &task.Cloudbrain) + tasks[i].ComputeResource = models.NPUResource } pager := context.NewPagination(int(count), setting.UI.IssuePagingNum, page, 5) @@ -364,7 +423,7 @@ func trainJobNewDataPrepare(ctx *context.Context) error { var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] ctx.Data["job_name"] = jobName - attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) + attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) if err != nil { ctx.ServerError("GetAllUserAttachments failed:", err) return err @@ -433,7 +492,7 @@ func trainJobErrorNewDataPrepare(ctx *context.Context, form auth.CreateModelArts var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] ctx.Data["job_name"] = jobName - attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) + attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) if err != nil { ctx.ServerError("GetAllUserAttachments failed:", err) return err @@ -521,7 +580,7 @@ func trainJobNewVersionDataPrepare(ctx *context.Context) error { var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] ctx.Data["job_name"] = task.JobName - attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) + attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) if err != nil { ctx.ServerError("GetAllUserAttachments failed:", err) return err @@ -610,7 +669,7 @@ func versionErrorDataPrepare(ctx *context.Context, form auth.CreateModelArtsTrai var jobName = cutString(ctx.User.Name, 5) + t.Format("2006010215") + strconv.Itoa(int(t.Unix()))[5:] ctx.Data["job_name"] = task.JobName - attachs, err := models.GetModelArtsUserAttachments(ctx.User.ID) + attachs, err := models.GetModelArtsTrainAttachments(ctx.User.ID) if err != nil { ctx.ServerError("GetAllUserAttachments failed:", err) return err @@ -1352,6 +1411,11 @@ func TrainJobDel(ctx *context.Context) { } } + //删除存储 + if len(VersionListTasks) > 0 { + DeleteJobStorage(VersionListTasks[0].JobName) + } + ctx.Redirect(setting.AppSubURL + ctx.Repo.RepoLink + "/modelarts/train-job") } @@ -1477,3 +1541,21 @@ func ModelDownload(ctx *context.Context) { } http.Redirect(ctx.Resp, ctx.Req.Request, url, http.StatusMovedPermanently) } + +func DeleteJobStorage(jobName string) error { + //delete local + localJobPath := setting.JobPath + jobName + err := os.RemoveAll(localJobPath) + if err != nil { + log.Error("RemoveAll(%s) failed:%v", localJobPath, err) + } + + //delete oss + dirPath := setting.CodePathPrefix + jobName + "/" + err = storage.ObsRemoveObject(setting.Bucket, dirPath) + if err != nil { + log.Error("ObsRemoveObject(%s) failed:%v", localJobPath, err) + } + + return nil +} diff --git a/routers/repo/view.go b/routers/repo/view.go index a5f2e1477..b08243240 100755 --- a/routers/repo/view.go +++ b/routers/repo/view.go @@ -605,7 +605,7 @@ func getContributorInfo(contributorInfos []*ContributorInfo, email string) *Cont func Home(ctx *context.Context) { if len(ctx.Repo.Units) > 0 { //get repo contributors info - contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath(), ctx.Repo.BranchName) if err == nil && contributors != nil { startTime := time.Now() var contributorInfos []*ContributorInfo @@ -924,7 +924,9 @@ func ContributorsAPI(ctx *context.Context) { count := 0 errorCode := 0 errorMsg := "" - contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath()) + + branchOrTag := ctx.Query("name") + contributors, err := git.GetContributors(ctx.Repo.Repository.RepoPath(), branchOrTag) var contributorInfos []*ContributorInfo if err == nil && contributors != nil { contributorInfoHash := make(map[string]*ContributorInfo) diff --git a/routers/routes/routes.go b/routers/routes/routes.go index 30e486b98..95931c723 100755 --- a/routers/routes/routes.go +++ b/routers/routes/routes.go @@ -315,6 +315,8 @@ func RegisterRoutes(m *macaron.Macaron) { }) m.Get("/", routers.Home) m.Get("/dashboard", routers.Dashboard) + go routers.SocketManager.Run() + m.Get("/action/notification", routers.ActionNotification) m.Get("/recommend/org", routers.RecommendOrgFromPromote) m.Get("/recommend/repo", routers.RecommendRepoFromPromote) m.Group("/explore", func() { @@ -625,6 +627,10 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/org", func() { m.Group("/:org", func() { m.Get("/members", org.Members) + m.Group("/org_tag", func() { + m.Get("/repo_list", org.GetTagRepos) + m.Post("/repo_submit", bindIgnErr(auth.SubmitReposOfTagForm{}), org.SubmitTags) + }) }, context.OrgAssignment()) }) m.Group("/org", func() { @@ -962,10 +968,11 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/cloudbrain", func() { m.Group("/:jobid", func() { m.Get("", reqRepoCloudBrainReader, repo.CloudBrainShow) - m.Get("/debug", reqRepoCloudBrainWriter, repo.CloudBrainDebug) + m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.CloudBrainDebug) m.Post("/commit_image", cloudbrain.AdminOrOwnerOrJobCreaterRight, bindIgnErr(auth.CommitImageCloudBrainForm{}), repo.CloudBrainCommitImage) m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainStop) m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDel) + m.Post("/restart", reqRepoCloudBrainWriter, repo.CloudBrainRestart) m.Get("/rate", reqRepoCloudBrainReader, repo.GetRate) m.Get("/models", reqRepoCloudBrainReader, repo.CloudBrainShowModels) m.Get("/download_model", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.CloudBrainDownloadModel) @@ -975,6 +982,7 @@ func RegisterRoutes(m *macaron.Macaron) { }, context.RepoRef()) m.Group("/modelmanage", func() { m.Post("/create_model", reqRepoModelManageWriter, repo.SaveModel) + m.Post("/create_new_model", reqRepoModelManageWriter, repo.SaveNewNameModel) m.Delete("/delete_model", repo.DeleteModel) m.Put("/modify_model", repo.ModifyModelInfo) m.Get("/show_model", reqRepoModelManageReader, repo.ShowModelTemplate) @@ -999,8 +1007,8 @@ func RegisterRoutes(m *macaron.Macaron) { m.Group("/notebook", func() { m.Group("/:jobid", func() { m.Get("", reqRepoCloudBrainReader, repo.NotebookShow) - m.Get("/debug", reqRepoCloudBrainWriter, repo.NotebookDebug) - m.Post("/stop", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookStop) + m.Get("/debug", cloudbrain.AdminOrJobCreaterRight, repo.NotebookDebug) + m.Post("/:action", reqRepoCloudBrainWriter, repo.NotebookManage) m.Post("/del", cloudbrain.AdminOrOwnerOrJobCreaterRight, repo.NotebookDel) }) m.Get("/create", reqRepoCloudBrainWriter, repo.NotebookNew) diff --git a/services/socketwrap/client.go b/services/socketwrap/client.go new file mode 100644 index 000000000..ce8dbb5e8 --- /dev/null +++ b/services/socketwrap/client.go @@ -0,0 +1,50 @@ +package socketwrap + +import ( + "code.gitea.io/gitea/models" + "code.gitea.io/gitea/modules/log" + "github.com/gorilla/websocket" +) + +type Client struct { + Manager *ClientsManager + + Conn *websocket.Conn + + Send chan *models.Action +} + +func (c *Client) WritePump() { + + defer func() { + c.Manager.Unregister <- c + c.Conn.Close() + }() + for { + select { + case message, ok := <-c.Send: + + if !ok { + c.Conn.WriteMessage(websocket.CloseMessage, []byte{}) + log.Warn("send socket is closed") + return + } + log.Warn("socket:", message) + err := c.Conn.WriteJSON(message) + if err != nil { + log.Warn("can not send message", err) + return + } + + n := len(c.Send) + for i := 0; i < n; i++ { + err = c.Conn.WriteJSON(<-c.Send) + if err != nil { + log.Warn("can not send message", err) + return + } + } + + } + } +} diff --git a/services/socketwrap/clientManager.go b/services/socketwrap/clientManager.go new file mode 100644 index 000000000..ac6ca0bed --- /dev/null +++ b/services/socketwrap/clientManager.go @@ -0,0 +1,46 @@ +package socketwrap + +import ( + "code.gitea.io/gitea/models" +) + +type ClientsManager struct { + Clients map[*Client]bool + Register chan *Client + Unregister chan *Client +} + +func NewClientsManager() *ClientsManager { + return &ClientsManager{ + Register: make(chan *Client), + Unregister: make(chan *Client), + Clients: make(map[*Client]bool), + } +} + +var LastTenActionsQueue = NewSyncQueue(10) + +func (h *ClientsManager) Run() { + for { + select { + case client := <-h.Register: + h.Clients[client] = true + case client := <-h.Unregister: + if _, ok := h.Clients[client]; ok { + delete(h.Clients, client) + close(client.Send) + } + case message := <-models.ActionChan: + LastTenActionsQueue.Push(message) + for client := range h.Clients { + select { + case client.Send <- message: + default: + close(client.Send) + delete(h.Clients, client) + } + } + + } + } +} diff --git a/services/socketwrap/syncqueue.go b/services/socketwrap/syncqueue.go new file mode 100644 index 000000000..c366ac23b --- /dev/null +++ b/services/socketwrap/syncqueue.go @@ -0,0 +1,34 @@ +package socketwrap + +import ( + "container/list" + "sync" +) + +type SyncQueue struct { + Queue *list.List + Mutex *sync.RWMutex + MaxSize int +} + +func (q *SyncQueue) Push(value interface{}) { + q.Mutex.Lock() + { + if q.Queue.Len() < q.MaxSize { + q.Queue.PushBack(value) + } else { + q.Queue.PushBack(value) + q.Queue.Remove(q.Queue.Front()) + } + } + + q.Mutex.Unlock() +} + +func NewSyncQueue(maxSize int) *SyncQueue { + return &SyncQueue{ + list.New(), + &sync.RWMutex{}, + maxSize, + } +} diff --git a/templates/org/home.tmpl b/templates/org/home.tmpl index 7e9970d2b..e03c28a9e 100755 --- a/templates/org/home.tmpl +++ b/templates/org/home.tmpl @@ -20,10 +20,11 @@
-
- {{template "org/navber" .}} - -
+ {{template "org/navber" .}} + {{template "org/select_pro" .}} +
+ +
{{if .CanCreateOrgRepo}} diff --git a/templates/org/member/members.tmpl b/templates/org/member/members.tmpl index 810a9eabb..87189c015 100644 --- a/templates/org/member/members.tmpl +++ b/templates/org/member/members.tmpl @@ -3,10 +3,11 @@ {{template "org/header" .}}
{{template "base/alert" .}} + {{template "org/navber" .}}
- {{template "org/navber" .}} + -
+
{{ range .Members}}
diff --git a/templates/org/navber.tmpl b/templates/org/navber.tmpl index 7bb2ff69c..f7e88c1e9 100755 --- a/templates/org/navber.tmpl +++ b/templates/org/navber.tmpl @@ -1,4 +1,4 @@ -
+ -
+ \ No newline at end of file +
--> + + + + \ No newline at end of file diff --git a/templates/org/select_pro.tmpl b/templates/org/select_pro.tmpl new file mode 100755 index 000000000..647bccd57 --- /dev/null +++ b/templates/org/select_pro.tmpl @@ -0,0 +1,319 @@ + +
+
+ {{if .tags}} + + 精选项目 + + + {{if .IsOrganizationOwner}} + {{svg "octicon-gear" 16}}自定义 + {{end}} + {{end}} + +
+
+ {{ range .tags}} + {{if eq .TagName "精选项目"}} + +
+ {{ range .RepoList}} +
+ +
+ + +
+ {{.Description}} +
+ + +
+ {{if .Topics }} +
+ {{range .Topics}} + {{if ne . "" }}{{.}}{{end}} + {{end}} + +
+ {{end}} + +
+ +
+ +
+ {{end}} +
+ + {{end}} + {{end}} + +
+ +
+ + + + \ No newline at end of file diff --git a/templates/org/team/teams.tmpl b/templates/org/team/teams.tmpl index 21bd47e9e..e7081b58f 100644 --- a/templates/org/team/teams.tmpl +++ b/templates/org/team/teams.tmpl @@ -3,12 +3,12 @@ {{template "org/header" .}}
{{template "base/alert" .}} - + {{template "org/navber" .}}
- {{template "org/navber" .}} + -
+
{{range .Teams}}
diff --git a/templates/repo/cloudbrain/new.tmpl b/templates/repo/cloudbrain/new.tmpl index 82f761c07..eb7805a23 100755 --- a/templates/repo/cloudbrain/new.tmpl +++ b/templates/repo/cloudbrain/new.tmpl @@ -93,6 +93,14 @@ display: none; } + .icons{ + /* position: absolute !important; + right: 150px; + top: 14px; + z-index: 2; */ + } + +
@@ -182,9 +190,10 @@
-
+
+ {{range .images}} @@ -261,9 +270,17 @@