Create separate Go file for build status updates

This commit is contained in:
mhmxs 2019-09-14 14:12:04 +02:00
parent 7fd68a706e
commit fd361ddf2a
6 changed files with 201 additions and 34 deletions

View file

@ -249,9 +249,10 @@ func ZombieKill(c *gin.Context) {
Config.Services.Queue.Error(context.Background(), fmt.Sprint(proc.ID), queue.ErrCancel)
}
build.Status = model.StatusKilled
build.Finished = time.Now().Unix()
store.FromContext(c).UpdateBuild(build)
if _, err := UpdateToStatusKilled(store.FromContext(c), *build); err != nil {
c.AbortWithError(500, err)
return
}
c.String(204, "")
}
@ -275,9 +276,6 @@ func PostApproval(c *gin.Context) {
c.String(500, "cannot decline a build with status %s", build.Status)
return
}
build.Status = model.StatusPending
build.Reviewed = time.Now().Unix()
build.Reviewer = user.Login
// fetch the build file from the database
configs, err := Config.Storage.Config.ConfigsForBuild(build.ID)
@ -289,12 +287,12 @@ func PostApproval(c *gin.Context) {
netrc, err := remote_.Netrc(user, repo)
if err != nil {
c.String(500, "Failed to generate netrc file. %s", err)
c.String(500, "failed to generate netrc file. %s", err)
return
}
if uerr := store.UpdateBuild(c, build); err != nil {
c.String(500, "error updating build. %s", uerr)
if build, err = UpdateToStatusPending(store.FromContext(c), *build, user.Login); err != nil {
c.String(500, "error updating build. %s", err)
return
}
@ -337,11 +335,9 @@ func PostApproval(c *gin.Context) {
}
buildItems, err := b.Build()
if err != nil {
build.Status = model.StatusError
build.Started = time.Now().Unix()
build.Finished = build.Started
build.Error = err.Error()
store.UpdateBuild(c, build)
if _, err = UpdateToStatusError(store.FromContext(c), *build, err); err != nil {
logrus.Errorf("Error setting error status of build for %s#%d. %s", repo.FullName, build.Number, err)
}
return
}
build = setBuildStepsOnBuild(b.Curr, buildItems)
@ -388,12 +384,8 @@ func PostDecline(c *gin.Context) {
c.String(500, "cannot decline a build with status %s", build.Status)
return
}
build.Status = model.StatusDeclined
build.Reviewed = time.Now().Unix()
build.Reviewer = user.Login
err = store.UpdateBuild(c, build)
if err != nil {
if _, err = UpdateToStatusDeclined(store.FromContext(c), *build, user.Login); err != nil {
c.String(500, "error updating build. %s", err)
return
}

120
server/buildStatus_test.go Normal file
View file

@ -0,0 +1,120 @@
// Copyright 2019 mhmxs.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package server
import (
"errors"
"testing"
"time"
"github.com/laszlocph/woodpecker/model"
)
const TIMEOUT = 3 * time.Second
type mockUpdateBuildStore struct {
}
func (m *mockUpdateBuildStore) UpdateBuild(build *model.Build) error {
return nil
}
func TestUpdateToStatusRunning(t *testing.T) {
t.Parallel()
build, _ := UpdateToStatusRunning(&mockUpdateBuildStore{}, model.Build{}, int64(1))
if model.StatusRunning != build.Status {
t.Errorf("Build status not equals '%s' != '%s'", model.StatusRunning, build.Status)
} else if int64(1) != build.Started {
t.Errorf("Build started not equals 1 != %d", build.Started)
}
}
func TestUpdateToStatusPending(t *testing.T) {
t.Parallel()
now := time.Now().Unix()
build, _ := UpdateToStatusPending(&mockUpdateBuildStore{}, model.Build{}, "Reviewer")
if model.StatusPending != build.Status {
t.Errorf("Build status not equals '%s' != '%s'", model.StatusPending, build.Status)
} else if "Reviewer" != build.Reviewer {
t.Errorf("Reviewer not equals 'Reviewer' != '%s'", build.Reviewer)
} else if now > build.Reviewed {
t.Errorf("Reviewed not updated %d !< %d", now, build.Reviewed)
}
}
func TestUpdateToStatusDeclined(t *testing.T) {
t.Parallel()
now := time.Now().Unix()
build, _ := UpdateToStatusDeclined(&mockUpdateBuildStore{}, model.Build{}, "Reviewer")
if model.StatusDeclined != build.Status {
t.Errorf("Build status not equals '%s' != '%s'", model.StatusDeclined, build.Status)
} else if "Reviewer" != build.Reviewer {
t.Errorf("Reviewer not equals 'Reviewer' != '%s'", build.Reviewer)
} else if now > build.Reviewed {
t.Errorf("Reviewed not updated %d !< %d", now, build.Reviewed)
}
}
func TestUpdateToStatusToDone(t *testing.T) {
t.Parallel()
build, _ := UpdateStatusToDone(&mockUpdateBuildStore{}, model.Build{}, "status", int64(1))
if "status" != build.Status {
t.Errorf("Build status not equals 'status' != '%s'", build.Status)
} else if int64(1) != build.Finished {
t.Errorf("Build finished not equals 1 != %d", build.Finished)
}
}
func TestUpdateToStatusError(t *testing.T) {
t.Parallel()
now := time.Now().Unix()
build, _ := UpdateToStatusError(&mockUpdateBuildStore{}, model.Build{}, errors.New("error"))
if "error" != build.Error {
t.Errorf("Build error not equals 'error' != '%s'", build.Error)
} else if model.StatusError != build.Status {
t.Errorf("Build status not equals '%s' != '%s'", model.StatusError, build.Status)
} else if now > build.Started {
t.Errorf("Started not updated %d !< %d", now, build.Started)
} else if build.Started != build.Finished {
t.Errorf("Build started and finished not equals %d != %d", build.Started, build.Finished)
}
}
func TestUpdateToStatusKilled(t *testing.T) {
t.Parallel()
now := time.Now().Unix()
build, _ := UpdateToStatusKilled(&mockUpdateBuildStore{}, model.Build{})
if model.StatusKilled != build.Status {
t.Errorf("Build status not equals '%s' != '%s'", model.StatusKilled, build.Status)
} else if now > build.Finished {
t.Errorf("Finished not updated %d !< %d", now, build.Finished)
}
}

65
server/builsStatus.go Normal file
View file

@ -0,0 +1,65 @@
// Copyright 2019 mhmxs.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package server
import (
"time"
"github.com/laszlocph/woodpecker/model"
)
type UpdateBuildStore interface {
UpdateBuild(*model.Build) error
}
func UpdateToStatusRunning(store UpdateBuildStore, build model.Build, started int64) (*model.Build, error) {
build.Status = model.StatusRunning
build.Started = started
return &build, store.UpdateBuild(&build)
}
func UpdateToStatusPending(store UpdateBuildStore, build model.Build, reviewer string) (*model.Build, error) {
build.Reviewer = reviewer
build.Status = model.StatusPending
build.Reviewed = time.Now().Unix()
return &build, store.UpdateBuild(&build)
}
func UpdateToStatusDeclined(store UpdateBuildStore, build model.Build, reviewer string) (*model.Build, error) {
build.Reviewer = reviewer
build.Status = model.StatusDeclined
build.Reviewed = time.Now().Unix()
return &build, store.UpdateBuild(&build)
}
func UpdateStatusToDone(store UpdateBuildStore, build model.Build, status string, stopped int64) (*model.Build, error) {
build.Status = status
build.Finished = stopped
return &build, store.UpdateBuild(&build)
}
func UpdateToStatusError(store UpdateBuildStore, build model.Build, err error) (*model.Build, error) {
build.Error = err.Error()
build.Status = model.StatusError
build.Started = time.Now().Unix()
build.Finished = build.Started
return &build, store.UpdateBuild(&build)
}
func UpdateToStatusKilled(store UpdateBuildStore, build model.Build) (*model.Build, error) {
build.Status = model.StatusKilled
build.Finished = time.Now().Unix()
return &build, store.UpdateBuild(&build)
}

View file

@ -259,11 +259,9 @@ func PostHook(c *gin.Context) {
}
buildItems, err := b.Build()
if err != nil {
build.Status = model.StatusError
build.Started = time.Now().Unix()
build.Finished = build.Started
build.Error = err.Error()
store.UpdateBuild(c, build)
if _, err = UpdateToStatusError(store.FromContext(c), *build, err); err != nil {
logrus.Errorf("Error setting error status of build for %s#%d. %s", repo.FullName, build.Number, err)
}
return
}
build = setBuildStepsOnBuild(b.Curr, buildItems)

View file

@ -326,9 +326,7 @@ func (s *RPC) Init(c context.Context, id string, state rpc.State) error {
}
if build.Status == model.StatusPending {
build.Status = model.StatusRunning
build.Started = state.Started
if err := s.store.UpdateBuild(build); err != nil {
if build, err = UpdateToStatusRunning(s.store, *build, state.Started); err != nil {
log.Printf("error: init: cannot update build_id %d state: %s", build.ID, err)
}
}
@ -394,9 +392,7 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error {
s.completeChildrenIfParentCompleted(procs, proc)
if !isThereRunningStage(procs) {
build.Status = buildStatus(procs)
build.Finished = proc.Stopped
if err := s.store.UpdateBuild(build); err != nil {
if build, err = UpdateStatusToDone(s.store, *build, buildStatus(procs), proc.Stopped); err != nil {
log.Printf("error: done: cannot update build_id %d final state: %s", build.ID, err)
}

View file

@ -249,7 +249,3 @@ func GetBuildQueue(c context.Context) ([]*model.Feed, error) {
func CreateBuild(c context.Context, build *model.Build, procs ...*model.Proc) error {
return FromContext(c).CreateBuild(build, procs...)
}
func UpdateBuild(c context.Context, build *model.Build) error {
return FromContext(c).UpdateBuild(build)
}