diff --git a/models/bots/run.go b/models/bots/run.go index 45eb7d675e..03170748c1 100644 --- a/models/bots/run.go +++ b/models/bots/run.go @@ -84,11 +84,15 @@ func (run *Run) LoadAttributes(ctx context.Context) error { } func (run *Run) TakeTime() time.Duration { + if run.Started == 0 { + return 0 + } started := run.Started.AsTime() if run.Status.IsDone() { return run.Stopped.AsTime().Sub(started) } - return time.Since(started) + run.Stopped.AsTime().Sub(started) + return time.Since(started).Truncate(time.Second) } func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) error { diff --git a/models/bots/task.go b/models/bots/task.go index 5a9054d162..c9719b6325 100644 --- a/models/bots/task.go +++ b/models/bots/task.go @@ -259,6 +259,14 @@ func CreateTaskForRunner(runner *Runner) (*Task, bool, error) { return nil, false, err } + if job.Run.Status.IsWaiting() { + job.Run.Status = StatusRunning + job.Run.Started = now + if err := UpdateRun(ctx, job.Run, "status", "started"); err != nil { + return nil, false, err + } + } + task.Job = job if err := commiter.Commit(); err != nil { diff --git a/modules/notification/bots/bots.go b/modules/notification/bots/bots.go index 798b9270cf..ef07f2323f 100644 --- a/modules/notification/bots/bots.go +++ b/modules/notification/bots/bots.go @@ -25,7 +25,6 @@ import ( "code.gitea.io/gitea/modules/repository" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/timeutil" "github.com/nektos/act/pkg/jobparser" ) @@ -95,7 +94,6 @@ func notify(repo *repo_model.Repository, doer *user_model.User, payload, ref str Event: evt, EventPayload: payload, Status: bots_model.StatusWaiting, - Started: timeutil.TimeStampNow(), } if len(run.Title) > 255 { run.Title = run.Title[:255] diff --git a/routers/web/dev/buildview.go b/routers/web/repo/builds/view.go similarity index 63% rename from routers/web/dev/buildview.go rename to routers/web/repo/builds/view.go index 571cb1d66b..ff5555c166 100644 --- a/routers/web/dev/buildview.go +++ b/routers/web/repo/builds/view.go @@ -1,4 +1,4 @@ -package dev +package builds import ( "fmt" @@ -12,14 +12,23 @@ import ( runnerv1 "gitea.com/gitea/proto-go/runner/v1" ) -func BuildView(ctx *context.Context) { - ctx.Data["RunIndex"] = ctx.ParamsInt64("run") - ctx.Data["JobIndex"] = ctx.ParamsInt64("job") +func View(ctx *context.Context) { + runIndex := ctx.ParamsInt64("run") + jobIndex := ctx.ParamsInt64("job") + ctx.Data["RunIndex"] = runIndex + ctx.Data["JobIndex"] = jobIndex - ctx.HTML(http.StatusOK, "dev/buildview") + job, _ := getRunJobs(ctx, runIndex, jobIndex) + if ctx.Written() { + return + } + run := job.Run + ctx.Data["Build"] = run + + ctx.HTML(http.StatusOK, tplViewBuild) } -type BuildViewRequest struct { +type ViewRequest struct { StepLogCursors []struct { StepIndex int `json:"stepIndex"` Cursor int64 `json:"cursor"` @@ -27,130 +36,112 @@ type BuildViewRequest struct { } `json:"stepLogCursors"` } -type BuildViewResponse struct { +type ViewResponse struct { StateData struct { BuildInfo struct { HTMLURL string `json:"htmlurl"` Title string `json:"title"` } `json:"buildInfo"` - AllJobGroups []BuildViewGroup `json:"allJobGroups"` + AllJobGroups []ViewGroup `json:"allJobGroups"` CurrentJobInfo struct { Title string `json:"title"` Detail string `json:"detail"` } `json:"currentJobInfo"` - CurrentJobSteps []BuildViewJobStep `json:"currentJobSteps"` + CurrentJobSteps []ViewJobStep `json:"currentJobSteps"` } `json:"stateData"` LogsData struct { - StreamingLogs []BuildViewStepLog `json:"streamingLogs"` + StreamingLogs []ViewStepLog `json:"streamingLogs"` } `json:"logsData"` } -type BuildViewGroup struct { - Summary string `json:"summary"` - Jobs []*BuildViewJob `json:"jobs"` +type ViewGroup struct { + Summary string `json:"summary"` + Jobs []*ViewJob `json:"jobs"` } -type BuildViewJob struct { +type ViewJob struct { Id int64 `json:"id"` Name string `json:"name"` Status string `json:"status"` } -type BuildViewJobStep struct { +type ViewJobStep struct { Summary string `json:"summary"` Duration float64 `json:"duration"` Status string `json:"status"` } -type BuildViewStepLog struct { - StepIndex int `json:"stepIndex"` - Cursor int64 `json:"cursor"` - Lines []BuildViewStepLogLine `json:"lines"` +type ViewStepLog struct { + StepIndex int `json:"stepIndex"` + Cursor int64 `json:"cursor"` + Lines []ViewStepLogLine `json:"lines"` } -type BuildViewStepLogLine struct { +type ViewStepLogLine struct { Ln int64 `json:"ln"` M string `json:"m"` T float64 `json:"t"` } -func BuildViewPost(ctx *context.Context) { - req := web.GetForm(ctx).(*BuildViewRequest) +func ViewPost(ctx *context.Context) { + req := web.GetForm(ctx).(*ViewRequest) runIndex := ctx.ParamsInt64("run") jobIndex := ctx.ParamsInt64("job") - run, err := bots_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex) - if err != nil { - if _, ok := err.(bots_model.ErrRunNotExist); ok { - ctx.Error(http.StatusNotFound, err.Error()) - return - } - ctx.Error(http.StatusInternalServerError, err.Error()) + current, jobs := getRunJobs(ctx, runIndex, jobIndex) + if ctx.Written() { return } - run.Repo = ctx.Repo.Repository + run := current.Run - jobs, err := bots_model.GetRunJobsByRunID(ctx, run.ID) - if err != nil { - ctx.Error(http.StatusInternalServerError, err.Error()) - return - } - - if jobIndex < 0 || jobIndex >= int64(len(jobs)) { - if len(jobs) == 0 { - ctx.Error(http.StatusNotFound, fmt.Sprintf("run %v has no job %v", runIndex, jobIndex)) - return - } - } - job := jobs[jobIndex] - - resp := &BuildViewResponse{} + resp := &ViewResponse{} resp.StateData.BuildInfo.Title = run.Title resp.StateData.BuildInfo.HTMLURL = run.HTMLURL() - respJobs := make([]*BuildViewJob, len(jobs)) + respJobs := make([]*ViewJob, len(jobs)) for i, v := range jobs { - respJobs[i] = &BuildViewJob{ + respJobs[i] = &ViewJob{ Id: v.ID, Name: v.Name, Status: v.Status.String(), } } - resp.StateData.AllJobGroups = []BuildViewGroup{ + resp.StateData.AllJobGroups = []ViewGroup{ { Summary: "Only One Group", // TODO: maybe we don't need job group Jobs: respJobs, }, } - if job != nil { + if current != nil { var task *bots_model.Task - if job.TaskID > 0 { - task, err = bots_model.GetTaskByID(ctx, job.TaskID) + if current.TaskID > 0 { + var err error + task, err = bots_model.GetTaskByID(ctx, current.TaskID) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } - task.Job = job + task.Job = current if err := task.LoadAttributes(ctx); err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } } - resp.StateData.CurrentJobInfo.Title = job.Name - resp.LogsData.StreamingLogs = make([]BuildViewStepLog, 0, len(req.StepLogCursors)) - if job.TaskID == 0 { + resp.StateData.CurrentJobInfo.Title = current.Name + resp.LogsData.StreamingLogs = make([]ViewStepLog, 0, len(req.StepLogCursors)) + if current.TaskID == 0 { resp.StateData.CurrentJobInfo.Detail = "wait to be pick up by a runner" } else { resp.StateData.CurrentJobInfo.Detail = "TODO: more detail info" // TODO: more detail info steps := task.FullSteps() - resp.StateData.CurrentJobSteps = make([]BuildViewJobStep, len(steps)) + resp.StateData.CurrentJobSteps = make([]ViewJobStep, len(steps)) for i, v := range steps { - resp.StateData.CurrentJobSteps[i] = BuildViewJobStep{ + resp.StateData.CurrentJobSteps[i] = ViewJobStep{ Summary: v.Name, Duration: float64(v.Stopped - v.Started), Status: v.Status.String(), @@ -165,21 +156,22 @@ func BuildViewPost(ctx *context.Context) { index := step.LogIndex + cursor.Cursor length := step.LogLength - cursor.Cursor offset := (*task.LogIndexes)[index] + var err error logRows, err = bots.ReadLogs(ctx, task.LogInStorage, task.LogFilename, offset, length) if err != nil { ctx.Error(http.StatusInternalServerError, err.Error()) return } } - logLines := make([]BuildViewStepLogLine, len(logRows)) + logLines := make([]ViewStepLogLine, len(logRows)) for i, row := range logRows { - logLines[i] = BuildViewStepLogLine{ + logLines[i] = ViewStepLogLine{ Ln: cursor.Cursor + int64(i), M: row.Content, T: float64(row.Time.AsTime().UnixNano()) / float64(time.Second), } } - resp.LogsData.StreamingLogs = append(resp.LogsData.StreamingLogs, BuildViewStepLog{ + resp.LogsData.StreamingLogs = append(resp.LogsData.StreamingLogs, ViewStepLog{ StepIndex: cursor.StepIndex, Cursor: cursor.Cursor + int64(len(logLines)), Lines: logLines, @@ -191,3 +183,34 @@ func BuildViewPost(ctx *context.Context) { ctx.JSON(http.StatusOK, resp) } + +func getRunJobs(ctx *context.Context, runIndex, jobIndex int64) (current *bots_model.RunJob, jobs []*bots_model.RunJob) { + run, err := bots_model.GetRunByIndex(ctx, ctx.Repo.Repository.ID, runIndex) + if err != nil { + if _, ok := err.(bots_model.ErrRunNotExist); ok { + ctx.Error(http.StatusNotFound, err.Error()) + return + } + ctx.Error(http.StatusInternalServerError, err.Error()) + return + } + run.Repo = ctx.Repo.Repository + + jobs, err = bots_model.GetRunJobsByRunID(ctx, run.ID) + if err != nil { + ctx.Error(http.StatusInternalServerError, err.Error()) + return nil, nil + } + for _, v := range jobs { + v.Run = run + } + + if jobIndex < 0 || jobIndex >= int64(len(jobs)) { + if len(jobs) == 0 { + ctx.Error(http.StatusNotFound, fmt.Sprintf("run %v has no job %v", runIndex, jobIndex)) + return nil, nil + } + } + current = jobs[jobIndex] + return +} diff --git a/routers/web/web.go b/routers/web/web.go index 9cd9dbaa37..3c8bcbe724 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -661,12 +661,6 @@ func RegisterRoutes(m *web.Route) { if !setting.IsProd { m.Any("/dev/termdemo", dev.TermDemo) - m.Combo("/dev/buildview/runs/{runid}"). - Get(dev.BuildView). - Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost) - m.Combo("/dev/buildview/runs/{runid}/jobs/{jobid}"). - Get(dev.BuildView). - Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost) } reqRepoAdmin := context.RequireRepoAdmin() @@ -1203,11 +1197,11 @@ func RegisterRoutes(m *web.Route) { m.Group("/runs/{run}", func() { m.Combo(""). - Get(dev.BuildView). - Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost) + Get(builds.View). + Post(bindIgnErr(builds.ViewRequest{}), builds.ViewPost) m.Combo("/jobs/{job}"). - Get(dev.BuildView). - Post(bindIgnErr(dev.BuildViewRequest{}), dev.BuildViewPost) + Get(builds.View). + Post(bindIgnErr(builds.ViewRequest{}), builds.ViewPost) }) }, reqRepoBuildsReader, builds.MustEnableBuilds) diff --git a/templates/dev/buildview.tmpl b/templates/dev/buildview.tmpl deleted file mode 100644 index cc0e4257f2..0000000000 --- a/templates/dev/buildview.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -{{template "base/head" .}} - -
- -
- -{{template "base/footer" .}} diff --git a/templates/repo/builds/view.tmpl b/templates/repo/builds/view.tmpl index da279aa97d..e95aea72b4 100644 --- a/templates/repo/builds/view.tmpl +++ b/templates/repo/builds/view.tmpl @@ -10,8 +10,8 @@ - {{template "repo/builds/view_left" .}} - {{template "repo/builds/view_content" .}} + +
{{template "base/footer" .}} diff --git a/templates/repo/builds/view_content.tmpl b/templates/repo/builds/view_content.tmpl deleted file mode 100644 index 095525bf60..0000000000 --- a/templates/repo/builds/view_content.tmpl +++ /dev/null @@ -1,22 +0,0 @@ -
-
-
-
-
-

Console Logs

-
-
-

-						
- 1 - Initialized empty Git repository in /drone/src/.git/ -0s
2+ git fetch origin +refs/heads/main: -0s
3From https://github.com/go-gitea/gitea -20s
4 * branch main -> FETCH_HEAD -20s
5 * [new branch] main -> origin/main -20s
6+ git checkout c8ec2261a99590f15699e9147a28e4b61c1c2ea5 -b main -20s
7Switched to a new branch 'main' -20s
-
-
diff --git a/templates/repo/builds/view_left.tmpl b/templates/repo/builds/view_left.tmpl deleted file mode 100644 index 6e0b60fc9e..0000000000 --- a/templates/repo/builds/view_left.tmpl +++ /dev/null @@ -1,18 +0,0 @@ -
-
-

Menu

- -
-