fix: use index of run

This commit is contained in:
Jason Song 2022-10-21 15:37:10 +08:00
parent 9292e9ebdb
commit 3d4d44dadf
6 changed files with 70 additions and 55 deletions

View File

@ -52,32 +52,32 @@ func (Run) TableName() string {
} }
func (run *Run) HTMLURL() string { func (run *Run) HTMLURL() string {
return fmt.Sprintf("%s/builds/run/%d", run.Repo.HTMLURL(), run.Index) return fmt.Sprintf("%s/builds/runs/%d", run.Repo.HTMLURL(), run.Index)
} }
// LoadAttributes load Repo TriggerUser if not loaded // LoadAttributes load Repo TriggerUser if not loaded
func (r *Run) LoadAttributes(ctx context.Context) error { func (run *Run) LoadAttributes(ctx context.Context) error {
if r == nil { if run == nil {
return nil return nil
} }
if r.Repo == nil { if run.Repo == nil {
repo, err := repo_model.GetRepositoryByIDCtx(ctx, r.RepoID) repo, err := repo_model.GetRepositoryByIDCtx(ctx, run.RepoID)
if err != nil { if err != nil {
return err return err
} }
r.Repo = repo run.Repo = repo
} }
if err := r.Repo.LoadAttributes(ctx); err != nil { if err := run.Repo.LoadAttributes(ctx); err != nil {
return err return err
} }
if r.TriggerUser == nil { if run.TriggerUser == nil {
u, err := user_model.GetUserByIDCtx(ctx, r.TriggerUserID) u, err := user_model.GetUserByIDCtx(ctx, run.TriggerUserID)
if err != nil { if err != nil {
return err return err
} }
r.TriggerUser = u run.TriggerUser = u
} }
return nil return nil
@ -159,10 +159,15 @@ func InsertRun(run *Run, jobs []*jobparser.SingleWorkflow) error {
// ErrRunNotExist represents an error for bot run not exist // ErrRunNotExist represents an error for bot run not exist
type ErrRunNotExist struct { type ErrRunNotExist struct {
ID int64 ID int64
RepoID int64
Index int64
} }
func (err ErrRunNotExist) Error() string { func (err ErrRunNotExist) Error() string {
if err.RepoID > 0 {
return fmt.Sprintf("run repe_id [%d] index [%d] is not exist", err.RepoID, err.Index)
}
return fmt.Sprintf("run [%d] is not exist", err.ID) return fmt.Sprintf("run [%d] is not exist", err.ID)
} }
@ -180,6 +185,24 @@ func GetRunByID(ctx context.Context, id int64) (*Run, error) {
return &run, nil return &run, nil
} }
func GetRunByIndex(ctx context.Context, repoID, index int64) (*Run, error) {
run := &Run{
RepoID: repoID,
Index: index,
}
has, err := db.GetEngine(ctx).Get(run)
if err != nil {
return nil, err
} else if !has {
return nil, ErrRunNotExist{
RepoID: repoID,
Index: index,
}
}
return run, nil
}
func UpdateRun(ctx context.Context, run *Run, cols ...string) error { func UpdateRun(ctx context.Context, run *Run, cols ...string) error {
sess := db.GetEngine(ctx).ID(run.ID) sess := db.GetEngine(ctx).ID(run.ID)
if len(cols) > 0 { if len(cols) > 0 {

View File

@ -84,7 +84,7 @@ func GetRunJobByID(ctx context.Context, id int64) (*RunJob, error) {
func GetRunJobsByRunID(ctx context.Context, runID int64) ([]*RunJob, error) { func GetRunJobsByRunID(ctx context.Context, runID int64) ([]*RunJob, error) {
var jobs []*RunJob var jobs []*RunJob
if err := db.GetEngine(ctx).Where("run_id=?", runID).Find(&jobs); err != nil { if err := db.GetEngine(ctx).Where("run_id=?", runID).OrderBy("id").Find(&jobs); err != nil {
return nil, err return nil, err
} }
return jobs, nil return jobs, nil

View File

@ -13,20 +13,8 @@ import (
) )
func BuildView(ctx *context.Context) { func BuildView(ctx *context.Context) {
runID := ctx.ParamsInt64("runid") ctx.Data["RunIndex"] = ctx.ParamsInt64("run")
ctx.Data["RunID"] = runID ctx.Data["JobIndex"] = ctx.ParamsInt64("job")
jobID := ctx.ParamsInt64("jobid")
if jobID <= 0 {
runJobs, err := bots_model.GetRunJobsByRunID(ctx, runID)
if err != nil {
return
}
if len(runJobs) <= 0 {
return
}
jobID = runJobs[0].ID
}
ctx.Data["JobID"] = jobID
ctx.HTML(http.StatusOK, "dev/buildview") ctx.HTML(http.StatusOK, "dev/buildview")
} }
@ -42,7 +30,8 @@ type BuildViewRequest struct {
type BuildViewResponse struct { type BuildViewResponse struct {
StateData struct { StateData struct {
BuildInfo struct { BuildInfo struct {
Title string `json:"title"` HTMLURL string `json:"htmlurl"`
Title string `json:"title"`
} `json:"buildInfo"` } `json:"buildInfo"`
AllJobGroups []BuildViewGroup `json:"allJobGroups"` AllJobGroups []BuildViewGroup `json:"allJobGroups"`
CurrentJobInfo struct { CurrentJobInfo struct {
@ -87,10 +76,10 @@ type BuildViewStepLogLine struct {
func BuildViewPost(ctx *context.Context) { func BuildViewPost(ctx *context.Context) {
req := web.GetForm(ctx).(*BuildViewRequest) req := web.GetForm(ctx).(*BuildViewRequest)
runID := ctx.ParamsInt64("runid") runIndex := ctx.ParamsInt64("run")
jobID := ctx.ParamsInt64("jobid") jobIndex := ctx.ParamsInt64("job")
run, err := bots_model.GetRunByID(ctx, runID) 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 {
ctx.Error(http.StatusNotFound, err.Error()) ctx.Error(http.StatusNotFound, err.Error())
@ -99,28 +88,25 @@ func BuildViewPost(ctx *context.Context) {
ctx.Error(http.StatusInternalServerError, err.Error()) ctx.Error(http.StatusInternalServerError, err.Error())
return return
} }
run.Repo = ctx.Repo.Repository
jobs, err := bots_model.GetRunJobsByRunID(ctx, run.ID) jobs, err := bots_model.GetRunJobsByRunID(ctx, run.ID)
if err != nil { if err != nil {
ctx.Error(http.StatusInternalServerError, err.Error()) ctx.Error(http.StatusInternalServerError, err.Error())
return return
} }
var job *bots_model.RunJob if jobIndex < 0 || jobIndex >= int64(len(jobs)) {
if jobID != 0 { if len(jobs) == 0 {
for _, v := range jobs { ctx.Error(http.StatusNotFound, fmt.Sprintf("run %v has no job %v", runIndex, jobIndex))
if v.ID == jobID {
job = v
break
}
}
if job == nil {
ctx.Error(http.StatusNotFound, fmt.Sprintf("run %v has no job %v", runID, jobID))
return return
} }
} }
job := jobs[jobIndex]
resp := &BuildViewResponse{} resp := &BuildViewResponse{}
resp.StateData.BuildInfo.Title = run.Title resp.StateData.BuildInfo.Title = run.Title
resp.StateData.BuildInfo.HTMLURL = run.HTMLURL()
respJobs := make([]*BuildViewJob, len(jobs)) respJobs := make([]*BuildViewJob, len(jobs))
for i, v := range jobs { for i, v := range jobs {

View File

@ -1201,13 +1201,14 @@ func RegisterRoutes(m *web.Route) {
m.Group("/builds", func() { m.Group("/builds", func() {
m.Get("", builds.List) m.Get("", builds.List)
m.Combo("/run/{runid}"). m.Group("/runs/{run}", func() {
Get(dev.BuildView). m.Combo("").
Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost) Get(dev.BuildView).
Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost)
m.Combo("/run/{runid}/jobs/{jobid}"). m.Combo("/jobs/{job}").
Get(dev.BuildView). Get(dev.BuildView).
Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost) Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost)
})
}, reqRepoBuildsReader, builds.MustEnableBuilds) }, reqRepoBuildsReader, builds.MustEnableBuilds)
m.Group("/wiki", func() { m.Group("/wiki", func() {

View File

@ -1,6 +1,6 @@
{{template "base/head" .}} {{template "base/head" .}}
<div id="repo-build-view" run-id="{{.RunID}}" job-id="{{.JobID}}" class="h-100"> <div id="repo-build-view" run-index="{{.RunIndex}}" job-index="{{.JobIndex}}" class="h-100">
</div> </div>

View File

@ -10,7 +10,7 @@
{{ jobGroup.summary }} {{ jobGroup.summary }}
</div> </div>
<div class="job-brief-list"> <div class="job-brief-list">
<a class="job-brief-item" v-for="job in jobGroup.jobs" :key="job.id" v-bind:href="'/dev/buildview/runs/'+runId+'/jobs/'+job.id"> <a class="job-brief-item" v-for="(job, index) in jobGroup.jobs" :key="job.id" v-bind:href="buildInfo.htmlurl+'/jobs/'+index">
<SvgIcon name="octicon-check-circle-fill" class="green" v-if="job.status === 'success'"/> <SvgIcon name="octicon-check-circle-fill" class="green" v-if="job.status === 'success'"/>
<SvgIcon name="octicon-skip" class="ui text grey" v-else-if="job.status === 'skipped'"/> <SvgIcon name="octicon-skip" class="ui text grey" v-else-if="job.status === 'skipped'"/>
<SvgIcon name="octicon-clock" class="ui text yellow" v-else-if="job.status === 'waiting'"/> <SvgIcon name="octicon-clock" class="ui text yellow" v-else-if="job.status === 'waiting'"/>
@ -72,14 +72,16 @@ import {SvgIcon} from '../svg.js';
import Vue, {createApp} from 'vue'; import Vue, {createApp} from 'vue';
import AnsiToHTML from `ansi-to-html`; import AnsiToHTML from `ansi-to-html`;
const {csrfToken} = window.config;
const sfc = { const sfc = {
name: 'RepoBuildView', name: 'RepoBuildView',
components: { components: {
SvgIcon, SvgIcon,
}, },
props: { props: {
runId: Number, runIndex: Number,
jobId: Number, jobIndex: Number,
}, },
data() { data() {
@ -255,9 +257,12 @@ const sfc = {
}, },
async fetchJobData(reqData) { async fetchJobData(reqData) {
const resp = await fetch(`/dev/buildview/runs/${this.runId}/jobs/${this.jobId}`, { // FIXME: hard code path const resp = await fetch(``, {
method: 'POST', method: 'POST',
headers: { 'Content-Type': 'application/json' }, headers: {
'Content-Type': 'application/json',
'X-Csrf-Token': csrfToken,
},
body: JSON.stringify(reqData), body: JSON.stringify(reqData),
}); });
return await resp.json(); return await resp.json();
@ -312,8 +317,8 @@ export function initRepositoryBuildView() {
if (!el) return; if (!el) return;
const view = createApp(sfc, { const view = createApp(sfc, {
jobId: el.getAttribute("job-id"), jobIndex: el.getAttribute("job-index"),
runId: el.getAttribute("run-id"), runIndex: el.getAttribute("run-index"),
}); });
view.mount(el); view.mount(el);
} }