mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-26 20:01:02 +00:00
restart build by clearing prior procs and logs
This commit is contained in:
parent
16a07e660a
commit
76006d28ac
11 changed files with 124 additions and 58 deletions
|
@ -8,6 +8,7 @@ type ProcStore interface {
|
|||
ProcList(*Build) ([]*Proc, error)
|
||||
ProcCreate([]*Proc) error
|
||||
ProcUpdate(*Proc) error
|
||||
ProcClear(*Build) error
|
||||
}
|
||||
|
||||
// Proc represents a process in the build pipeline.
|
||||
|
|
107
server/build.go
107
server/build.go
|
@ -403,13 +403,6 @@ func PostBuild(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
procs, err := store.FromContext(c).ProcList(build)
|
||||
if err != nil {
|
||||
logrus.Errorf("failure to get build %d procs. %s", build.Number, err)
|
||||
c.AbortWithError(404, err)
|
||||
return
|
||||
}
|
||||
|
||||
// must not restart a running build
|
||||
if build.Status == model.StatusPending || build.Status == model.StatusRunning {
|
||||
c.String(409, "Cannot re-start a started build")
|
||||
|
@ -422,11 +415,12 @@ func PostBuild(c *gin.Context) {
|
|||
build.ID = 0
|
||||
build.Number = 0
|
||||
build.Parent = num
|
||||
for _, proc := range procs {
|
||||
proc.ID = 0
|
||||
proc.BuildID = 0
|
||||
}
|
||||
err := store.CreateBuild(c, build, procs...)
|
||||
build.Status = model.StatusPending
|
||||
build.Started = 0
|
||||
build.Finished = 0
|
||||
build.Enqueued = time.Now().UTC().Unix()
|
||||
build.Error = ""
|
||||
err = store.CreateBuild(c, build)
|
||||
if err != nil {
|
||||
c.String(500, err.Error())
|
||||
return
|
||||
|
@ -440,6 +434,26 @@ func PostBuild(c *gin.Context) {
|
|||
build.Event = event
|
||||
}
|
||||
build.Deploy = c.DefaultQuery("deploy_to", build.Deploy)
|
||||
} else {
|
||||
// todo move this to database tier
|
||||
// and wrap inside a transaction
|
||||
build.Status = model.StatusPending
|
||||
build.Started = 0
|
||||
build.Finished = 0
|
||||
build.Enqueued = time.Now().UTC().Unix()
|
||||
build.Error = ""
|
||||
|
||||
err = store.FromContext(c).ProcClear(build)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(500)
|
||||
return
|
||||
}
|
||||
|
||||
err = store.UpdateBuild(c, build)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(500)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Read query string parameters into buildParams, exclude reserved params
|
||||
|
@ -454,34 +468,6 @@ func PostBuild(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
// todo move this to database tier
|
||||
// and wrap inside a transaction
|
||||
build.Status = model.StatusPending
|
||||
build.Started = 0
|
||||
build.Finished = 0
|
||||
build.Enqueued = time.Now().UTC().Unix()
|
||||
build.Error = ""
|
||||
for _, proc := range procs {
|
||||
for k, v := range buildParams {
|
||||
proc.Environ[k] = v
|
||||
}
|
||||
proc.Error = ""
|
||||
proc.State = model.StatusPending
|
||||
proc.Started = 0
|
||||
proc.Stopped = 0
|
||||
proc.ExitCode = 0
|
||||
proc.Machine = ""
|
||||
store.FromContext(c).ProcUpdate(proc)
|
||||
}
|
||||
|
||||
err = store.UpdateBuild(c, build)
|
||||
if err != nil {
|
||||
c.AbortWithStatus(500)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(202, build)
|
||||
|
||||
// get the previous build so that we can send
|
||||
// on status change notifications
|
||||
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
|
||||
|
@ -499,23 +485,54 @@ func PostBuild(c *gin.Context) {
|
|||
Link: httputil.GetURL(c.Request),
|
||||
Yaml: string(raw),
|
||||
}
|
||||
// TODO inject environment varibles !!!!!! buildParams
|
||||
items, err := b.Build()
|
||||
if err != nil {
|
||||
build.Status = model.StatusError
|
||||
build.Started = time.Now().Unix()
|
||||
build.Finished = build.Started
|
||||
build.Error = err.Error()
|
||||
c.JSON(500, build)
|
||||
return
|
||||
}
|
||||
|
||||
for i, item := range items {
|
||||
// TODO prevent possible index out of bounds
|
||||
item.Proc.ID = procs[i].ID
|
||||
var pcounter = len(items)
|
||||
for _, item := range items {
|
||||
build.Procs = append(build.Procs, item.Proc)
|
||||
store.FromContext(c).ProcUpdate(item.Proc)
|
||||
item.Proc.BuildID = build.ID
|
||||
|
||||
// TODO update child procs too!
|
||||
for _, stage := range item.Config.Stages {
|
||||
var gid int
|
||||
for _, step := range stage.Steps {
|
||||
pcounter++
|
||||
if gid == 0 {
|
||||
gid = pcounter
|
||||
}
|
||||
proc := &model.Proc{
|
||||
BuildID: build.ID,
|
||||
Name: step.Alias,
|
||||
PID: pcounter,
|
||||
PPID: item.Proc.PID,
|
||||
PGID: gid,
|
||||
State: model.StatusPending,
|
||||
}
|
||||
build.Procs = append(build.Procs, proc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err = store.FromContext(c).ProcCreate(build.Procs)
|
||||
if err != nil {
|
||||
logrus.Errorf("cannot restart %s#%d: %s", repo.FullName, build.Number, err)
|
||||
build.Status = model.StatusError
|
||||
build.Started = time.Now().Unix()
|
||||
build.Finished = build.Started
|
||||
build.Error = err.Error()
|
||||
c.JSON(500, build)
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(202, build)
|
||||
|
||||
//
|
||||
// publish topic
|
||||
|
|
|
@ -46,3 +46,14 @@ func (db *datastore) ProcCreate(procs []*model.Proc) error {
|
|||
func (db *datastore) ProcUpdate(proc *model.Proc) error {
|
||||
return meddler.Update(db, "procs", proc)
|
||||
}
|
||||
|
||||
func (db *datastore) ProcClear(build *model.Build) (err error) {
|
||||
stmt1 := sql.Lookup(db.driver, "files-delete-build")
|
||||
stmt2 := sql.Lookup(db.driver, "procs-delete-build")
|
||||
_, err = db.Exec(stmt1, build.ID)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = db.Exec(stmt2, build.ID)
|
||||
return
|
||||
}
|
||||
|
|
|
@ -219,19 +219,19 @@ func TestProcIndexes(t *testing.T) {
|
|||
t.Errorf("Unexpected error: dupliate pid")
|
||||
}
|
||||
|
||||
// fail due to duplicate process name
|
||||
if err := s.ProcCreate([]*model.Proc{
|
||||
{
|
||||
BuildID: 1,
|
||||
PID: 2,
|
||||
PPID: 1,
|
||||
PGID: 1,
|
||||
State: "success",
|
||||
Name: "build",
|
||||
},
|
||||
}); err == nil {
|
||||
t.Errorf("Unexpected error: dupliate name")
|
||||
}
|
||||
// // fail due to duplicate process name
|
||||
// if err := s.ProcCreate([]*model.Proc{
|
||||
// {
|
||||
// BuildID: 1,
|
||||
// PID: 2,
|
||||
// PPID: 1,
|
||||
// PGID: 1,
|
||||
// State: "success",
|
||||
// Name: "build",
|
||||
// },
|
||||
// }); err == nil {
|
||||
// t.Errorf("Unexpected error: dupliate name")
|
||||
// }
|
||||
}
|
||||
|
||||
// func TestProcCascade(t *testing.T) {
|
||||
|
|
|
@ -39,3 +39,7 @@ SELECT
|
|||
FROM files
|
||||
WHERE file_proc_id = $1
|
||||
AND file_name = $2
|
||||
|
||||
-- name: files-delete-build
|
||||
|
||||
DELETE FROM files WHERE file_build_id = $1
|
||||
|
|
|
@ -80,3 +80,7 @@ FROM procs
|
|||
WHERE proc_build_id = $1
|
||||
AND proc_ppid = $2
|
||||
AND proc_name = $3
|
||||
|
||||
-- name: procs-delete-build
|
||||
|
||||
DELETE FROM procs WHERE proc_build_id = $1
|
||||
|
|
|
@ -9,10 +9,12 @@ var index = map[string]string{
|
|||
"files-find-build": filesFindBuild,
|
||||
"files-find-proc-name": filesFindProcName,
|
||||
"files-find-proc-name-data": filesFindProcNameData,
|
||||
"files-delete-build": filesDeleteBuild,
|
||||
"procs-find-id": procsFindId,
|
||||
"procs-find-build": procsFindBuild,
|
||||
"procs-find-build-pid": procsFindBuildPid,
|
||||
"procs-find-build-ppid": procsFindBuildPpid,
|
||||
"procs-delete-build": procsDeleteBuild,
|
||||
}
|
||||
|
||||
var filesFindBuild = `
|
||||
|
@ -57,6 +59,10 @@ WHERE file_proc_id = $1
|
|||
AND file_name = $2
|
||||
`
|
||||
|
||||
var filesDeleteBuild = `
|
||||
DELETE FROM files WHERE file_build_id = $1
|
||||
`
|
||||
|
||||
var procsFindId = `
|
||||
SELECT
|
||||
proc_id
|
||||
|
@ -139,3 +145,7 @@ WHERE proc_build_id = $1
|
|||
AND proc_ppid = $2
|
||||
AND proc_name = $3
|
||||
`
|
||||
|
||||
var procsDeleteBuild = `
|
||||
DELETE FROM procs WHERE proc_build_id = $1
|
||||
`
|
||||
|
|
|
@ -39,3 +39,7 @@ SELECT
|
|||
FROM files
|
||||
WHERE file_proc_id = ?
|
||||
AND file_name = ?
|
||||
|
||||
-- name: files-delete-build
|
||||
|
||||
DELETE FROM files WHERE file_build_id = ?
|
||||
|
|
|
@ -80,3 +80,7 @@ FROM procs
|
|||
WHERE proc_build_id = ?
|
||||
AND proc_ppid = ?
|
||||
AND proc_name = ?
|
||||
|
||||
-- name: procs-delete-build
|
||||
|
||||
DELETE FROM procs WHERE proc_build_id = ?
|
||||
|
|
|
@ -9,10 +9,12 @@ var index = map[string]string{
|
|||
"files-find-build": filesFindBuild,
|
||||
"files-find-proc-name": filesFindProcName,
|
||||
"files-find-proc-name-data": filesFindProcNameData,
|
||||
"files-delete-build": filesDeleteBuild,
|
||||
"procs-find-id": procsFindId,
|
||||
"procs-find-build": procsFindBuild,
|
||||
"procs-find-build-pid": procsFindBuildPid,
|
||||
"procs-find-build-ppid": procsFindBuildPpid,
|
||||
"procs-delete-build": procsDeleteBuild,
|
||||
}
|
||||
|
||||
var filesFindBuild = `
|
||||
|
@ -57,6 +59,10 @@ WHERE file_proc_id = ?
|
|||
AND file_name = ?
|
||||
`
|
||||
|
||||
var filesDeleteBuild = `
|
||||
DELETE FROM files WHERE file_build_id = ?
|
||||
`
|
||||
|
||||
var procsFindId = `
|
||||
SELECT
|
||||
proc_id
|
||||
|
@ -139,3 +145,7 @@ WHERE proc_build_id = ?
|
|||
AND proc_ppid = ?
|
||||
AND proc_name = ?
|
||||
`
|
||||
|
||||
var procsDeleteBuild = `
|
||||
DELETE FROM procs WHERE proc_build_id = ?
|
||||
`
|
||||
|
|
|
@ -151,6 +151,7 @@ type Store interface {
|
|||
ProcList(*model.Build) ([]*model.Proc, error)
|
||||
ProcCreate([]*model.Proc) error
|
||||
ProcUpdate(*model.Proc) error
|
||||
ProcClear(*model.Build) error
|
||||
|
||||
LogFind(*model.Proc) (io.ReadCloser, error)
|
||||
LogSave(*model.Proc, io.Reader) error
|
||||
|
|
Loading…
Reference in a new issue