feat: rerun jobs

This commit is contained in:
Jason Song 2022-11-07 14:16:51 +08:00
parent 37224e2441
commit 0b62e1da74
4 changed files with 66 additions and 7 deletions

View File

@ -1,18 +1,21 @@
package builds package builds
import ( import (
"context"
"fmt" "fmt"
"net/http" "net/http"
"time" "time"
bots_model "code.gitea.io/gitea/models/bots" bots_model "code.gitea.io/gitea/models/bots"
"code.gitea.io/gitea/models/db"
"code.gitea.io/gitea/modules/bots" "code.gitea.io/gitea/modules/bots"
"code.gitea.io/gitea/modules/context" context_module "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web"
runnerv1 "gitea.com/gitea/proto-go/runner/v1" runnerv1 "gitea.com/gitea/proto-go/runner/v1"
"xorm.io/builder"
) )
func View(ctx *context.Context) { func View(ctx *context_module.Context) {
ctx.Data["PageIsBuilds"] = true ctx.Data["PageIsBuilds"] = true
runIndex := ctx.ParamsInt64("run") runIndex := ctx.ParamsInt64("run")
jobIndex := ctx.ParamsInt64("job") jobIndex := ctx.ParamsInt64("job")
@ -85,7 +88,7 @@ type ViewStepLogLine struct {
T float64 `json:"t"` T float64 `json:"t"`
} }
func ViewPost(ctx *context.Context) { func ViewPost(ctx *context_module.Context) {
req := web.GetForm(ctx).(*ViewRequest) req := web.GetForm(ctx).(*ViewRequest)
runIndex := ctx.ParamsInt64("run") runIndex := ctx.ParamsInt64("run")
jobIndex := ctx.ParamsInt64("job") jobIndex := ctx.ParamsInt64("job")
@ -187,7 +190,37 @@ func ViewPost(ctx *context.Context) {
ctx.JSON(http.StatusOK, resp) ctx.JSON(http.StatusOK, resp)
} }
func getRunJobs(ctx *context.Context, runIndex, jobIndex int64) (current *bots_model.RunJob, jobs []*bots_model.RunJob) { func Rerun(ctx *context_module.Context) {
runIndex := ctx.ParamsInt64("run")
jobIndex := ctx.ParamsInt64("job")
job, _ := getRunJobs(ctx, runIndex, jobIndex)
if ctx.Written() {
return
}
status := job.Status
if !status.IsDone() {
ctx.JSON(http.StatusOK, struct{}{})
return
}
job.TaskID = 0
job.Status = bots_model.StatusWaiting
job.Started = 0
job.Stopped = 0
if err := db.WithTx(func(ctx context.Context) error {
_, err := bots_model.UpdateRunJob(ctx, job, builder.Eq{"status": status}, "task_id", "status", "started", "stopped")
return err
}, ctx); err != nil {
ctx.Error(http.StatusInternalServerError, err.Error())
return
}
ctx.JSON(http.StatusOK, struct{}{})
}
func getRunJobs(ctx *context_module.Context, runIndex, jobIndex int64) (current *bots_model.RunJob, jobs []*bots_model.RunJob) {
run, err := bots_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex) run, err := bots_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex)
if err != nil { if err != nil {
if _, ok := err.(bots_model.ErrRunNotExist); ok { if _, ok := err.(bots_model.ErrRunNotExist); ok {

View File

@ -1217,9 +1217,13 @@ func RegisterRoutes(m *web.Route) {
m.Combo(""). m.Combo("").
Get(builds.View). Get(builds.View).
Post(bindIgnErr(builds.ViewRequest{}), builds.ViewPost) Post(bindIgnErr(builds.ViewRequest{}), builds.ViewPost)
m.Combo("/jobs/{job}"). m.Group("/jobs/{job}", func() {
Get(builds.View). m.Combo("").
Post(bindIgnErr(builds.ViewRequest{}), builds.ViewPost) Get(builds.View).
Post(bindIgnErr(builds.ViewRequest{}), builds.ViewPost)
m.Post("/rerun", builds.Rerun)
})
}) })
}, reqRepoBuildsReader, builds.MustEnableBuilds) }, reqRepoBuildsReader, builds.MustEnableBuilds)

View File

@ -18,6 +18,9 @@
<SvgIcon name="octicon-meter" class="ui text yellow" class-name="job-status-rotate" v-else-if="job.status === 'running'"/> <SvgIcon name="octicon-meter" class="ui text yellow" class-name="job-status-rotate" v-else-if="job.status === 'running'"/>
<SvgIcon name="octicon-x-circle-fill" class="red" v-else/> <SvgIcon name="octicon-x-circle-fill" class="red" v-else/>
{{ job.name }} {{ job.name }}
<button class="job-brief-rerun" @click="rerunJob(index)" v-if="job.status !== 'waiting' && job.status !== 'blocked' && job.status !== 'running'">
<SvgIcon name="octicon-sync"/>
</button>
</a> </a>
</div> </div>
</div> </div>
@ -146,6 +149,17 @@ const sfc = {
this.loadJobData(); // try to load the data immediately instead of waiting for next timer interval this.loadJobData(); // try to load the data immediately instead of waiting for next timer interval
} }
}, },
// rerun a job
rerunJob(idx) {
fetch(this.buildInfo.htmlurl+'/jobs/'+idx+'/rerun', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Csrf-Token': csrfToken,
},
body: {},
});
},
formatDuration(d) { formatDuration(d) {
d = Math.round(d); d = Math.round(d);
@ -359,6 +373,12 @@ export function initRepositoryBuildView() {
background: #f8f8f8; background: #f8f8f8;
border-radius: 5px; border-radius: 5px;
text-decoration: none; text-decoration: none;
button.job-brief-rerun {
float: right;
border: none;
background-color: transparent;
outline: none
};
} }
} }
} }

View File

@ -29,6 +29,7 @@ import octiconXCircleFill from '../../public/img/svg/octicon-x-circle-fill.svg';
import octiconSkip from '../../public/img/svg/octicon-skip.svg'; import octiconSkip from '../../public/img/svg/octicon-skip.svg';
import octiconMeter from '../../public/img/svg/octicon-meter.svg'; import octiconMeter from '../../public/img/svg/octicon-meter.svg';
import octiconBlocked from '../../public/img/svg/octicon-blocked.svg'; import octiconBlocked from '../../public/img/svg/octicon-blocked.svg';
import octiconSync from '../../public/img/svg/octicon-sync.svg';
export const svgs = { export const svgs = {
@ -63,6 +64,7 @@ export const svgs = {
'octicon-skip': octiconSkip, 'octicon-skip': octiconSkip,
'octicon-meter': octiconMeter, 'octicon-meter': octiconMeter,
'octicon-blocked': octiconBlocked, 'octicon-blocked': octiconBlocked,
'octicon-sync': octiconSync,
}; };