restart build by clearing prior procs and logs

This commit is contained in:
Brad Rydzewski 2017-04-04 19:50:15 +09:00
parent 16a07e660a
commit 76006d28ac
11 changed files with 124 additions and 58 deletions

View file

@ -8,6 +8,7 @@ type ProcStore interface {
ProcList(*Build) ([]*Proc, error) ProcList(*Build) ([]*Proc, error)
ProcCreate([]*Proc) error ProcCreate([]*Proc) error
ProcUpdate(*Proc) error ProcUpdate(*Proc) error
ProcClear(*Build) error
} }
// Proc represents a process in the build pipeline. // Proc represents a process in the build pipeline.

View file

@ -403,13 +403,6 @@ func PostBuild(c *gin.Context) {
return 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 // must not restart a running build
if build.Status == model.StatusPending || build.Status == model.StatusRunning { if build.Status == model.StatusPending || build.Status == model.StatusRunning {
c.String(409, "Cannot re-start a started build") c.String(409, "Cannot re-start a started build")
@ -422,11 +415,12 @@ func PostBuild(c *gin.Context) {
build.ID = 0 build.ID = 0
build.Number = 0 build.Number = 0
build.Parent = num build.Parent = num
for _, proc := range procs { build.Status = model.StatusPending
proc.ID = 0 build.Started = 0
proc.BuildID = 0 build.Finished = 0
} build.Enqueued = time.Now().UTC().Unix()
err := store.CreateBuild(c, build, procs...) build.Error = ""
err = store.CreateBuild(c, build)
if err != nil { if err != nil {
c.String(500, err.Error()) c.String(500, err.Error())
return return
@ -440,6 +434,26 @@ func PostBuild(c *gin.Context) {
build.Event = event build.Event = event
} }
build.Deploy = c.DefaultQuery("deploy_to", build.Deploy) 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 // 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 // get the previous build so that we can send
// on status change notifications // on status change notifications
last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID) last, _ := store.GetBuildLastBefore(c, repo, build.Branch, build.ID)
@ -499,24 +485,55 @@ func PostBuild(c *gin.Context) {
Link: httputil.GetURL(c.Request), Link: httputil.GetURL(c.Request),
Yaml: string(raw), Yaml: string(raw),
} }
// TODO inject environment varibles !!!!!! buildParams
items, err := b.Build() items, err := b.Build()
if err != nil { if err != nil {
build.Status = model.StatusError build.Status = model.StatusError
build.Started = time.Now().Unix() build.Started = time.Now().Unix()
build.Finished = build.Started build.Finished = build.Started
build.Error = err.Error() build.Error = err.Error()
c.JSON(500, build)
return return
} }
for i, item := range items { var pcounter = len(items)
// TODO prevent possible index out of bounds for _, item := range items {
item.Proc.ID = procs[i].ID
build.Procs = append(build.Procs, item.Proc) 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 // publish topic
// //

View file

@ -46,3 +46,14 @@ func (db *datastore) ProcCreate(procs []*model.Proc) error {
func (db *datastore) ProcUpdate(proc *model.Proc) error { func (db *datastore) ProcUpdate(proc *model.Proc) error {
return meddler.Update(db, "procs", proc) 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
}

View file

@ -219,19 +219,19 @@ func TestProcIndexes(t *testing.T) {
t.Errorf("Unexpected error: dupliate pid") t.Errorf("Unexpected error: dupliate pid")
} }
// fail due to duplicate process name // // fail due to duplicate process name
if err := s.ProcCreate([]*model.Proc{ // if err := s.ProcCreate([]*model.Proc{
{ // {
BuildID: 1, // BuildID: 1,
PID: 2, // PID: 2,
PPID: 1, // PPID: 1,
PGID: 1, // PGID: 1,
State: "success", // State: "success",
Name: "build", // Name: "build",
}, // },
}); err == nil { // }); err == nil {
t.Errorf("Unexpected error: dupliate name") // t.Errorf("Unexpected error: dupliate name")
} // }
} }
// func TestProcCascade(t *testing.T) { // func TestProcCascade(t *testing.T) {

View file

@ -39,3 +39,7 @@ SELECT
FROM files FROM files
WHERE file_proc_id = $1 WHERE file_proc_id = $1
AND file_name = $2 AND file_name = $2
-- name: files-delete-build
DELETE FROM files WHERE file_build_id = $1

View file

@ -80,3 +80,7 @@ FROM procs
WHERE proc_build_id = $1 WHERE proc_build_id = $1
AND proc_ppid = $2 AND proc_ppid = $2
AND proc_name = $3 AND proc_name = $3
-- name: procs-delete-build
DELETE FROM procs WHERE proc_build_id = $1

View file

@ -9,10 +9,12 @@ var index = map[string]string{
"files-find-build": filesFindBuild, "files-find-build": filesFindBuild,
"files-find-proc-name": filesFindProcName, "files-find-proc-name": filesFindProcName,
"files-find-proc-name-data": filesFindProcNameData, "files-find-proc-name-data": filesFindProcNameData,
"files-delete-build": filesDeleteBuild,
"procs-find-id": procsFindId, "procs-find-id": procsFindId,
"procs-find-build": procsFindBuild, "procs-find-build": procsFindBuild,
"procs-find-build-pid": procsFindBuildPid, "procs-find-build-pid": procsFindBuildPid,
"procs-find-build-ppid": procsFindBuildPpid, "procs-find-build-ppid": procsFindBuildPpid,
"procs-delete-build": procsDeleteBuild,
} }
var filesFindBuild = ` var filesFindBuild = `
@ -57,6 +59,10 @@ WHERE file_proc_id = $1
AND file_name = $2 AND file_name = $2
` `
var filesDeleteBuild = `
DELETE FROM files WHERE file_build_id = $1
`
var procsFindId = ` var procsFindId = `
SELECT SELECT
proc_id proc_id
@ -139,3 +145,7 @@ WHERE proc_build_id = $1
AND proc_ppid = $2 AND proc_ppid = $2
AND proc_name = $3 AND proc_name = $3
` `
var procsDeleteBuild = `
DELETE FROM procs WHERE proc_build_id = $1
`

View file

@ -39,3 +39,7 @@ SELECT
FROM files FROM files
WHERE file_proc_id = ? WHERE file_proc_id = ?
AND file_name = ? AND file_name = ?
-- name: files-delete-build
DELETE FROM files WHERE file_build_id = ?

View file

@ -80,3 +80,7 @@ FROM procs
WHERE proc_build_id = ? WHERE proc_build_id = ?
AND proc_ppid = ? AND proc_ppid = ?
AND proc_name = ? AND proc_name = ?
-- name: procs-delete-build
DELETE FROM procs WHERE proc_build_id = ?

View file

@ -9,10 +9,12 @@ var index = map[string]string{
"files-find-build": filesFindBuild, "files-find-build": filesFindBuild,
"files-find-proc-name": filesFindProcName, "files-find-proc-name": filesFindProcName,
"files-find-proc-name-data": filesFindProcNameData, "files-find-proc-name-data": filesFindProcNameData,
"files-delete-build": filesDeleteBuild,
"procs-find-id": procsFindId, "procs-find-id": procsFindId,
"procs-find-build": procsFindBuild, "procs-find-build": procsFindBuild,
"procs-find-build-pid": procsFindBuildPid, "procs-find-build-pid": procsFindBuildPid,
"procs-find-build-ppid": procsFindBuildPpid, "procs-find-build-ppid": procsFindBuildPpid,
"procs-delete-build": procsDeleteBuild,
} }
var filesFindBuild = ` var filesFindBuild = `
@ -57,6 +59,10 @@ WHERE file_proc_id = ?
AND file_name = ? AND file_name = ?
` `
var filesDeleteBuild = `
DELETE FROM files WHERE file_build_id = ?
`
var procsFindId = ` var procsFindId = `
SELECT SELECT
proc_id proc_id
@ -139,3 +145,7 @@ WHERE proc_build_id = ?
AND proc_ppid = ? AND proc_ppid = ?
AND proc_name = ? AND proc_name = ?
` `
var procsDeleteBuild = `
DELETE FROM procs WHERE proc_build_id = ?
`

View file

@ -151,6 +151,7 @@ type Store interface {
ProcList(*model.Build) ([]*model.Proc, error) ProcList(*model.Build) ([]*model.Proc, error)
ProcCreate([]*model.Proc) error ProcCreate([]*model.Proc) error
ProcUpdate(*model.Proc) error ProcUpdate(*model.Proc) error
ProcClear(*model.Build) error
LogFind(*model.Proc) (io.ReadCloser, error) LogFind(*model.Proc) (io.ReadCloser, error)
LogSave(*model.Proc, io.Reader) error LogSave(*model.Proc, io.Reader) error