From a1ddfb82009b6fbba2f27e11b8280ef53d47dd35 Mon Sep 17 00:00:00 2001 From: Jason Song Date: Mon, 14 Nov 2022 16:05:55 +0800 Subject: [PATCH] feat: use new FullSteps --- go.sum | 2 - models/bots/status.go | 7 +- models/bots/task.go | 50 -------------- modules/bots/task_state.go | 102 ++++++++++++++++++++++++++++ modules/bots/task_state_test.go | 113 ++++++++++++++++++++++++++++++++ routers/web/repo/builds/view.go | 3 +- 6 files changed, 223 insertions(+), 54 deletions(-) create mode 100644 modules/bots/task_state.go create mode 100644 modules/bots/task_state_test.go diff --git a/go.sum b/go.sum index ff785cae89..850750a9aa 100644 --- a/go.sum +++ b/go.sum @@ -85,8 +85,6 @@ gitea.com/gitea/act v0.0.0-20221104080934-57978c14b59d h1:Xfdo11dwHpcjFtH0qebucf gitea.com/gitea/act v0.0.0-20221104080934-57978c14b59d/go.mod h1:lpzib6X73FHLSaTqTakan1xcsCAVhlZvPSpLns7jkRo= gitea.com/gitea/act_runner v0.0.0-20221015084035-e63e22e8c81d h1:WdZqNKX1TB0vH1nOFZhoYdesEGFwvwpKGkwjGaGCmgo= gitea.com/gitea/act_runner v0.0.0-20221015084035-e63e22e8c81d/go.mod h1:ZDTf3CZrtttQj0EzduNKPRUBPIrPOK6cdx/LFFVX+EE= -gitea.com/gitea/proto-go v0.0.0-20221014123629-9116865c883b h1:TSz7VRHfnM/5JwGPgIAjSlDIvcr4pTGfuRMtgMxttmg= -gitea.com/gitea/proto-go v0.0.0-20221014123629-9116865c883b/go.mod h1:hD8YwSHusjwjEEgubW6XFvnZuNhMZTHz6lwjfltEt/Y= gitea.com/gitea/proto-go v0.0.0-20221028125601-35c4f6b05835 h1:27PhT7Nli/pgRo1bDYVZ+hlCKuF9cfFuo+y9muaPVJY= gitea.com/gitea/proto-go v0.0.0-20221028125601-35c4f6b05835/go.mod h1:hD8YwSHusjwjEEgubW6XFvnZuNhMZTHz6lwjfltEt/Y= gitea.com/go-chi/binding v0.0.0-20220309004920-114340dabecb h1:Yy0Bxzc8R2wxiwXoG/rECGplJUSpXqCsog9PuJFgiHs= diff --git a/models/bots/status.go b/models/bots/status.go index 5f8e66179c..626b45f5d0 100644 --- a/models/bots/status.go +++ b/models/bots/status.go @@ -25,7 +25,12 @@ func (s Status) String() string { // IsDone returns whether the Status is final func (s Status) IsDone() bool { - return s > StatusUnknown && s <= StatusSkipped + return s.In(StatusSuccess, StatusFailure, StatusCancelled, StatusSkipped) +} + +// HasRun returns whether the Status is a result of running +func (s Status) HasRun() bool { + return s.In(StatusSuccess, StatusFailure) } func (s Status) IsSuccess() bool { diff --git a/models/bots/task.go b/models/bots/task.go index 3589e36f4f..c09015644c 100644 --- a/models/bots/task.go +++ b/models/bots/task.go @@ -190,56 +190,6 @@ func (task *Task) LoadAttributes(ctx context.Context) error { return nil } -// FullSteps returns steps with "Set up job" and "Complete job" -func (task *Task) FullSteps() []*TaskStep { - // TODO: The logic here is too complex and tricky, may need to be rewritten - - var firstStep, lastStep *TaskStep - if l := len(task.Steps); l > 0 { - firstStep = task.Steps[0] - lastStep = task.Steps[l-1] - } - var index int64 - - headStep := &TaskStep{ - Name: "Set up job", - LogLength: task.LogLength, - Started: task.Started, - Status: StatusWaiting, - } - if task.LogLength > 0 { - headStep.Status = StatusRunning - } - if firstStep != nil && firstStep.LogLength > 0 { - headStep.LogLength = firstStep.LogIndex - headStep.Stopped = firstStep.Started - headStep.Status = StatusSuccess - } - index += headStep.LogLength - - for _, step := range task.Steps { - index += step.LogLength - } - - tailStep := &TaskStep{ - Name: "Complete job", - Stopped: task.Stopped, - Status: StatusWaiting, - } - if lastStep != nil && lastStep.Result != runnerv1.Result_RESULT_UNSPECIFIED { - tailStep.LogIndex = index - tailStep.LogLength = task.LogLength - tailStep.LogIndex - tailStep.Started = lastStep.Stopped - tailStep.Status = StatusSuccess - } - steps := make([]*TaskStep, 0, len(task.Steps)+2) - steps = append(steps, headStep) - steps = append(steps, task.Steps...) - steps = append(steps, tailStep) - - return steps -} - func (task *Task) GenerateToken() error { salt, err := util.CryptoRandomString(10) if err != nil { diff --git a/modules/bots/task_state.go b/modules/bots/task_state.go new file mode 100644 index 0000000000..e453c448b5 --- /dev/null +++ b/modules/bots/task_state.go @@ -0,0 +1,102 @@ +// Copyright 2022 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 bots + +import ( + bots_model "code.gitea.io/gitea/models/bots" +) + +const ( + preStepName = "Set up job" + postStepName = "Complete job" +) + +// FullSteps returns steps with "Set up job" and "Complete job" +func FullSteps(task *bots_model.Task) []*bots_model.TaskStep { + if len(task.Steps) == 0 { + return fullStepsOfEmptySteps(task) + } + + firstStep := task.Steps[0] + var logIndex int64 + + preStep := &bots_model.TaskStep{ + Name: preStepName, + LogLength: task.LogLength, + Started: task.Started, + Status: bots_model.StatusRunning, + } + + if firstStep.Status.HasRun() || firstStep.Status.IsRunning() { + preStep.LogLength = firstStep.LogIndex + preStep.Stopped = firstStep.Started + preStep.Status = bots_model.StatusSuccess + } else if task.Status.IsDone() { + preStep.Stopped = task.Stopped + preStep.Status = bots_model.StatusFailure + } + logIndex += preStep.LogLength + + var lastHasRunStep *bots_model.TaskStep + for _, step := range task.Steps { + if step.Status.HasRun() { + lastHasRunStep = step + } + logIndex += step.LogLength + } + if lastHasRunStep == nil { + lastHasRunStep = preStep + } + + postStep := &bots_model.TaskStep{ + Name: postStepName, + Status: bots_model.StatusWaiting, + } + if task.Status.IsDone() { + postStep.LogIndex = logIndex + postStep.LogLength = task.LogLength - postStep.LogIndex + postStep.Status = task.Status + postStep.Started = lastHasRunStep.Stopped + postStep.Stopped = task.Stopped + } + ret := make([]*bots_model.TaskStep, 0, len(task.Steps)+2) + ret = append(ret, preStep) + ret = append(ret, task.Steps...) + ret = append(ret, postStep) + + return ret +} + +func fullStepsOfEmptySteps(task *bots_model.Task) []*bots_model.TaskStep { + preStep := &bots_model.TaskStep{ + Name: preStepName, + LogLength: task.LogLength, + Started: task.Started, + Stopped: task.Stopped, + Status: bots_model.StatusRunning, + } + + postStep := &bots_model.TaskStep{ + Name: postStepName, + LogIndex: task.LogLength, + Started: task.Stopped, + Stopped: task.Stopped, + Status: bots_model.StatusWaiting, + } + + if task.Status.IsDone() { + preStep.Status = task.Status + if preStep.Status.IsSuccess() { + postStep.Status = bots_model.StatusSuccess + } else { + postStep.Status = bots_model.StatusCancelled + } + } + + return []*bots_model.TaskStep{ + preStep, + postStep, + } +} diff --git a/modules/bots/task_state_test.go b/modules/bots/task_state_test.go new file mode 100644 index 0000000000..908ae7c22e --- /dev/null +++ b/modules/bots/task_state_test.go @@ -0,0 +1,113 @@ +// Copyright 2022 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 bots + +import ( + "testing" + + bots_model "code.gitea.io/gitea/models/bots" + + "github.com/stretchr/testify/assert" +) + +func TestFullSteps(t *testing.T) { + tests := []struct { + name string + task *bots_model.Task + want []*bots_model.TaskStep + }{ + { + name: "regular", + task: &bots_model.Task{ + Steps: []*bots_model.TaskStep{ + {Status: bots_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090}, + }, + Status: bots_model.StatusSuccess, + Started: 10000, + Stopped: 10100, + LogLength: 100, + }, + want: []*bots_model.TaskStep{ + {Name: preStepName, Status: bots_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010}, + {Status: bots_model.StatusSuccess, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 10090}, + {Name: postStepName, Status: bots_model.StatusSuccess, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 10100}, + }, + }, + { + name: "failed step", + task: &bots_model.Task{ + Steps: []*bots_model.TaskStep{ + {Status: bots_model.StatusSuccess, LogIndex: 10, LogLength: 20, Started: 10010, Stopped: 10020}, + {Status: bots_model.StatusFailure, LogIndex: 30, LogLength: 60, Started: 10020, Stopped: 10090}, + {Status: bots_model.StatusCancelled, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + }, + Status: bots_model.StatusFailure, + Started: 10000, + Stopped: 10100, + LogLength: 100, + }, + want: []*bots_model.TaskStep{ + {Name: preStepName, Status: bots_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010}, + {Status: bots_model.StatusSuccess, LogIndex: 10, LogLength: 20, Started: 10010, Stopped: 10020}, + {Status: bots_model.StatusFailure, LogIndex: 30, LogLength: 60, Started: 10020, Stopped: 10090}, + {Status: bots_model.StatusCancelled, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + {Name: postStepName, Status: bots_model.StatusFailure, LogIndex: 90, LogLength: 10, Started: 10090, Stopped: 10100}, + }, + }, + { + name: "first step is running", + task: &bots_model.Task{ + Steps: []*bots_model.TaskStep{ + {Status: bots_model.StatusRunning, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 0}, + }, + Status: bots_model.StatusRunning, + Started: 10000, + Stopped: 10100, + LogLength: 100, + }, + want: []*bots_model.TaskStep{ + {Name: preStepName, Status: bots_model.StatusSuccess, LogIndex: 0, LogLength: 10, Started: 10000, Stopped: 10010}, + {Status: bots_model.StatusRunning, LogIndex: 10, LogLength: 80, Started: 10010, Stopped: 0}, + {Name: postStepName, Status: bots_model.StatusWaiting, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + }, + }, + { + name: "first step has canceled", + task: &bots_model.Task{ + Steps: []*bots_model.TaskStep{ + {Status: bots_model.StatusCancelled, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + }, + Status: bots_model.StatusFailure, + Started: 10000, + Stopped: 10100, + LogLength: 100, + }, + want: []*bots_model.TaskStep{ + {Name: preStepName, Status: bots_model.StatusFailure, LogIndex: 0, LogLength: 100, Started: 10000, Stopped: 10100}, + {Status: bots_model.StatusCancelled, LogIndex: 0, LogLength: 0, Started: 0, Stopped: 0}, + {Name: postStepName, Status: bots_model.StatusFailure, LogIndex: 100, LogLength: 0, Started: 10100, Stopped: 10100}, + }, + }, + { + name: "empty steps", + task: &bots_model.Task{ + Steps: []*bots_model.TaskStep{}, + Status: bots_model.StatusSuccess, + Started: 10000, + Stopped: 10100, + LogLength: 100, + }, + want: []*bots_model.TaskStep{ + {Name: preStepName, Status: bots_model.StatusSuccess, LogIndex: 0, LogLength: 100, Started: 10000, Stopped: 10100}, + {Name: postStepName, Status: bots_model.StatusSuccess, LogIndex: 100, LogLength: 0, Started: 10100, Stopped: 10100}, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + assert.Equalf(t, tt.want, FullSteps(tt.task), "FullSteps(%v)", tt.task) + }) + } +} diff --git a/routers/web/repo/builds/view.go b/routers/web/repo/builds/view.go index f67c079df6..14d27912c9 100644 --- a/routers/web/repo/builds/view.go +++ b/routers/web/repo/builds/view.go @@ -11,6 +11,7 @@ import ( "code.gitea.io/gitea/modules/bots" context_module "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/web" + runnerv1 "gitea.com/gitea/proto-go/runner/v1" "xorm.io/builder" ) @@ -143,7 +144,7 @@ func ViewPost(ctx *context_module.Context) { } else { resp.StateData.CurrentJobInfo.Detail = "TODO: more detail info" // TODO: more detail info - steps := task.FullSteps() + steps := bots.FullSteps(task) resp.StateData.CurrentJobSteps = make([]ViewJobStep, len(steps)) for i, v := range steps {