@@ -11,20 +11,20 @@ import ( | |||
"xorm.io/builder" | |||
) | |||
type CloudbrainStatus int8 | |||
type CloudbrainStatus string | |||
const ( | |||
JobWaiting CloudbrainStatus = iota | |||
JobStopped | |||
JobSucceeded | |||
JobFailed | |||
JobWaiting CloudbrainStatus = "WAITING" | |||
JobStopped CloudbrainStatus = "STOPPED" | |||
JobSucceeded CloudbrainStatus = "SUCCEEDED" | |||
JobFailed CloudbrainStatus = "FAILED" | |||
) | |||
type Cloudbrain struct { | |||
ID int64 `xorm:"pk autoincr"` | |||
JobID string `xorm:"INDEX NOT NULL"` | |||
JobName string | |||
Status int32 `xorm:"INDEX"` | |||
Status string `xorm:"INDEX"` | |||
UserID int64 `xorm:"INDEX"` | |||
RepoID int64 `xorm:"INDEX"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
@@ -79,9 +79,9 @@ type CloudbrainsOptions struct { | |||
RepoID int64 // include all repos if empty | |||
UserID int64 | |||
JobID int64 | |||
JobStatus CloudbrainStatus | |||
SortType string | |||
CloudbrainIDs []int64 | |||
// JobStatus CloudbrainStatus | |||
} | |||
type TaskPod struct { | |||
TaskRoleStatus struct { | |||
@@ -127,7 +127,7 @@ type JobResultPayload struct { | |||
AppProgress string `json:"appProgress"` | |||
AppTrackingURL string `json:"appTrackingUrl"` | |||
AppLaunchedTime int64 `json:"appLaunchedTime"` | |||
AppCompletedTime int64 `json:"appCompletedTime"` | |||
AppCompletedTime interface{} `json:"appCompletedTime"` | |||
AppExitCode int `json:"appExitCode"` | |||
AppExitDiagnostics string `json:"appExitDiagnostics"` | |||
AppExitType interface{} `json:"appExitType"` | |||
@@ -196,16 +196,16 @@ func Cloudbrains(opts *CloudbrainsOptions) ([]*Cloudbrain, int64, error) { | |||
) | |||
} | |||
switch opts.JobStatus { | |||
case JobWaiting: | |||
cond.And(builder.Eq{"cloudbrain.status": int(JobWaiting)}) | |||
case JobFailed: | |||
cond.And(builder.Eq{"cloudbrain.status": int(JobFailed)}) | |||
case JobStopped: | |||
cond.And(builder.Eq{"cloudbrain.status": int(JobStopped)}) | |||
case JobSucceeded: | |||
cond.And(builder.Eq{"cloudbrain.status": int(JobSucceeded)}) | |||
} | |||
// switch opts.JobStatus { | |||
// case JobWaiting: | |||
// cond.And(builder.Eq{"cloudbrain.status": int(JobWaiting)}) | |||
// case JobFailed: | |||
// cond.And(builder.Eq{"cloudbrain.status": int(JobFailed)}) | |||
// case JobStopped: | |||
// cond.And(builder.Eq{"cloudbrain.status": int(JobStopped)}) | |||
// case JobSucceeded: | |||
// cond.And(builder.Eq{"cloudbrain.status": int(JobSucceeded)}) | |||
// } | |||
if len(opts.CloudbrainIDs) > 0 { | |||
cond.And(builder.In("cloudbrain.id", opts.CloudbrainIDs)) | |||
@@ -244,6 +244,17 @@ func CreateCloudbrain(cloudbrain *Cloudbrain) (err error) { | |||
return nil | |||
} | |||
func GetRepoCloudBrainByJobID(repoID int64, jobID string) (*Cloudbrain, error) { | |||
cb := &Cloudbrain{JobID: jobID, RepoID: repoID} | |||
has, err := x.Get(cb) | |||
if err != nil { | |||
return nil, err | |||
} else if !has { | |||
return nil, errors.New("cloudbrain task is not found") | |||
} | |||
return cb, nil | |||
} | |||
func GetCloudbrainByJobID(jobID string) (*Cloudbrain, error) { | |||
cb := &Cloudbrain{JobID: jobID} | |||
has, err := x.Get(cb) | |||
@@ -12,7 +12,7 @@ func addCloudBrainTable(x *xorm.Engine) error { | |||
ID int64 `xorm:"pk autoincr"` | |||
JobID string `xorm:"INDEX NOT NULL"` | |||
JobName string | |||
Status int32 `xorm:"INDEX"` | |||
Status string `xorm:"INDEX"` | |||
UserID int64 `xorm:"INDEX"` | |||
RepoID int64 `xorm:"INDEX"` | |||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` | |||
@@ -39,7 +39,7 @@ func GenerateTask(ctx *context.Context, jobName, image, command string) error { | |||
var jobID = jobResult.Payload["jobId"].(string) | |||
err = models.CreateCloudbrain(&models.Cloudbrain{ | |||
Status: int32(models.JobWaiting), | |||
Status: string(models.JobWaiting), | |||
UserID: ctx.User.ID, | |||
RepoID: ctx.Repo.Repository.ID, | |||
JobID: jobID, | |||
@@ -849,6 +849,9 @@ func RegisterRoutes(m *macaron.Macaron) { | |||
Delete(reqToken(), repo.DeleteTopic) | |||
}, reqAdmin()) | |||
}, reqAnyRepoReader()) | |||
m.Group("/cloudbrain", func() { | |||
m.Get("/:jobid", repo.GetCloudbrainTask) | |||
}, reqRepoReader(models.UnitTypeCloudBrain)) | |||
}, repoAssignment()) | |||
}) | |||
@@ -0,0 +1,75 @@ | |||
// Copyright 2016 The Gogs Authors. All rights reserved. | |||
// Copyright 2018 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 repo | |||
import ( | |||
"net/http" | |||
"time" | |||
"code.gitea.io/gitea/models" | |||
"code.gitea.io/gitea/modules/cloudbrain" | |||
"code.gitea.io/gitea/modules/context" | |||
) | |||
// cloudbrain get job task by jobid | |||
func GetCloudbrainTask(ctx *context.APIContext) { | |||
// swagger:operation GET /repos/{owner}/{repo}/cloudbrain/{jobid} cloudbrain jobTask | |||
// --- | |||
// summary: Get a single task | |||
// produces: | |||
// - application/json | |||
// parameters: | |||
// - name: owner | |||
// in: path | |||
// description: owner of the repo | |||
// type: string | |||
// required: true | |||
// - name: repo | |||
// in: path | |||
// description: name of the repo | |||
// type: string | |||
// required: true | |||
// - name: jobid | |||
// in: path | |||
// description: id of cloudbrain jobid | |||
// type: string | |||
// required: true | |||
// responses: | |||
// "200": | |||
// "$ref": "#/responses/Label" | |||
var ( | |||
err error | |||
) | |||
jobID := ctx.Params(":jobid") | |||
repoID := ctx.Repo.Repository.ID | |||
_, err = models.GetRepoCloudBrainByJobID(repoID, jobID) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
jobResult, err := cloudbrain.GetJob(jobID) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
result, err := models.ConvertToJobResultPayload(jobResult.Payload) | |||
if err != nil { | |||
ctx.NotFound(err) | |||
return | |||
} | |||
ctx.JSON(http.StatusOK, map[string]interface{}{ | |||
"JobID": result.Config.JobID, | |||
"JobStatus": result.JobStatus.State, | |||
"SubState": result.JobStatus.SubState, | |||
"CreatedTime": time.Unix(result.JobStatus.CreatedTime/1000, 0).Format("2006-01-02 15:04:05"), | |||
"CompletedTime": time.Unix(result.JobStatus.CompletedTime/1000, 0).Format("2006-01-02 15:04:05"), | |||
}) | |||
} |
@@ -33,27 +33,24 @@ | |||
{{range .Tasks}} | |||
<div class="ui grid item"> | |||
<div class="row"> | |||
<div class="five wide column"> | |||
<div class="seven wide column"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}"> | |||
<span class="fitted">{{svg "octicon-tasklist" 16}}</span> | |||
<span class="fitted">{{.JobName}}</span> | |||
</a> | |||
</div> | |||
<div class="two wide column"> | |||
waiting | |||
<div class="four wide column job-status" id="{{.JobID}}" data-repopath="{{$.RepoRelPath}}" data-jobid="{{.JobID}}"> | |||
{{.Status}} | |||
</div> | |||
<div class="three wide column"> | |||
<span class="ui text center">{{svg "octicon-flame" 16}} {{TimeSinceUnix .CreatedUnix $.Lang}}</span> | |||
</div> | |||
<div class="two wide column"> | |||
<span class="ui text center clipboard">18h 0m 8s</span> | |||
</div> | |||
<div class="two wide column"> | |||
<span class="ui text center clipboard">{{.Status}}</span> | |||
</div> | |||
<div class="two wide column"> | |||
<span class="ui text center clipboard">再次提交</span> | |||
<span class="ui text center clipboard"> | |||
<a class="title" href="{{$.Link}}/{{.JobID}}"> | |||
<span class="fitted">查看</span> | |||
</a> | |||
</span> | |||
</div> | |||
</div> | |||
</div> | |||
@@ -66,3 +63,23 @@ | |||
</div> | |||
</div> | |||
{{template "base/footer" .}} | |||
<script> | |||
$( document ).ready(function() { | |||
$( ".job-status" ).each(( index, job ) => { | |||
const jobID = job.dataset.jobid; | |||
const repoPath = job.dataset.repopath; | |||
if (job.textContent.trim() != 'WAITING') { | |||
return | |||
} | |||
$.get( `/api/v1/repos/${repoPath}/cloudbrain/${jobID}`, ( data ) => { | |||
const jobID = data.JobID | |||
const status = data.JobStatus | |||
$('#'+ jobID).text(status) | |||
// console.log(data) | |||
}).fail(function(err) { | |||
console.log( err ); | |||
}); | |||
}); | |||
}); | |||
</script> |
@@ -2324,6 +2324,44 @@ | |||
} | |||
} | |||
}, | |||
"/repos/{owner}/{repo}/cloudbrain/{jobid}": { | |||
"get": { | |||
"produces": [ | |||
"application/json" | |||
], | |||
"tags": [ | |||
"cloudbrain" | |||
], | |||
"summary": "Get a single task", | |||
"operationId": "jobTask", | |||
"parameters": [ | |||
{ | |||
"type": "string", | |||
"description": "owner of the repo", | |||
"name": "owner", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "name of the repo", | |||
"name": "repo", | |||
"in": "path", | |||
"required": true | |||
}, | |||
{ | |||
"type": "string", | |||
"description": "id of cloudbrain jobid", | |||
"name": "jobid", | |||
"in": "path", | |||
"required": true | |||
} | |||
], | |||
"responses": { | |||
"200": {} | |||
} | |||
} | |||
}, | |||
"/repos/{owner}/{repo}/collaborators": { | |||
"get": { | |||
"produces": [ | |||