You've already forked woodpecker
							
							
				mirror of
				https://github.com/woodpecker-ci/woodpecker.git
				synced 2025-10-30 23:27:39 +02:00 
			
		
		
		
	use separate log table
This commit is contained in:
		| @@ -1,7 +0,0 @@ | ||||
| package model | ||||
|  | ||||
| // type Log struct { | ||||
| // 	ID    int64  `meddler:"log_id,pk"` | ||||
| // 	JobID int64  `meddler:"log_job_id"` | ||||
| // 	Data  []byte `meddler:"log_data"` | ||||
| // } | ||||
| @@ -104,7 +104,7 @@ func Load(middleware ...gin.HandlerFunc) http.Handler { | ||||
| 			repo.GET("", server.GetRepo) | ||||
| 			repo.GET("/builds", server.GetBuilds) | ||||
| 			repo.GET("/builds/:number", server.GetBuild) | ||||
| 			repo.GET("/logs/:number/:job", server.GetBuildLogs) | ||||
| 			repo.GET("/logs/:number/:ppid/:proc", server.GetBuildLogs) | ||||
| 			repo.POST("/sign", session.MustPush, server.Sign) | ||||
|  | ||||
| 			repo.GET("/secrets", session.MustPush, server.GetSecrets) | ||||
|   | ||||
| @@ -77,7 +77,8 @@ func GetBuildLogs(c *gin.Context) { | ||||
| 	// parse the build number and job sequence number from | ||||
| 	// the repquest parameter. | ||||
| 	num, _ := strconv.Atoi(c.Params.ByName("number")) | ||||
| 	seq, _ := strconv.Atoi(c.Params.ByName("job")) | ||||
| 	ppid, _ := strconv.Atoi(c.Params.ByName("ppid")) | ||||
| 	name := c.Params.ByName("proc") | ||||
|  | ||||
| 	build, err := store.GetBuildNumber(c, repo, num) | ||||
| 	if err != nil { | ||||
| @@ -85,13 +86,13 @@ func GetBuildLogs(c *gin.Context) { | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	proc, err := store.FromContext(c).ProcFind(build, seq) | ||||
| 	proc, err := store.FromContext(c).ProcChild(build, ppid, name) | ||||
| 	if err != nil { | ||||
| 		c.AbortWithError(404, err) | ||||
| 		return | ||||
| 	} | ||||
|  | ||||
| 	rc, err := store.FromContext(c).FileRead(proc, "logs.json") | ||||
| 	rc, err := store.FromContext(c).LogFind(proc) | ||||
| 	if err != nil { | ||||
| 		c.AbortWithError(404, err) | ||||
| 		return | ||||
|   | ||||
| @@ -111,15 +111,21 @@ func (s *RPC) Update(c context.Context, id string, state rpc.State) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	proc, err := s.store.ProcLoad(procID) | ||||
| 	pproc, err := s.store.ProcLoad(procID) | ||||
| 	if err != nil { | ||||
| 		log.Printf("error: rpc.update: cannot find proc with id %d: %s", procID, err) | ||||
| 		log.Printf("error: rpc.update: cannot find pproc with id %d: %s", procID, err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	build, err := s.store.GetBuild(proc.BuildID) | ||||
| 	build, err := s.store.GetBuild(pproc.BuildID) | ||||
| 	if err != nil { | ||||
| 		log.Printf("error: cannot find build with id %d: %s", proc.BuildID, err) | ||||
| 		log.Printf("error: cannot find build with id %d: %s", pproc.BuildID, err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	proc, err := s.store.ProcChild(build, pproc.PID, state.Proc) | ||||
| 	if err != nil { | ||||
| 		log.Printf("error: cannot find proc with name %s: %s", state.Proc, err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| @@ -133,6 +139,10 @@ func (s *RPC) Update(c context.Context, id string, state rpc.State) error { | ||||
| 		proc.Stopped = state.Finished | ||||
| 		proc.ExitCode = state.ExitCode | ||||
| 		proc.Error = state.Error | ||||
| 		proc.State = model.StatusSuccess | ||||
| 		if state.ExitCode != 0 || state.Error != "" { | ||||
| 			proc.State = model.StatusFailure | ||||
| 		} | ||||
| 	} else { | ||||
| 		proc.Started = state.Started | ||||
| 		proc.State = model.StatusRunning | ||||
| @@ -165,12 +175,31 @@ func (s *RPC) Upload(c context.Context, id string, file *rpc.File) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	proc, err := s.store.ProcLoad(procID) | ||||
| 	pproc, err := s.store.ProcLoad(procID) | ||||
| 	if err != nil { | ||||
| 		log.Printf("error: cannot find proc with id %d: %s", procID, err) | ||||
| 		log.Printf("error: cannot find parent proc with id %d: %s", procID, err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	build, err := s.store.GetBuild(pproc.BuildID) | ||||
| 	if err != nil { | ||||
| 		log.Printf("error: cannot find build with id %d: %s", pproc.BuildID, err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	proc, err := s.store.ProcChild(build, pproc.PID, file.Proc) | ||||
| 	if err != nil { | ||||
| 		log.Printf("error: cannot find child proc with name %s: %s", file.Proc, err) | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if file.Mime == "application/json+logs" { | ||||
| 		return s.store.LogSave( | ||||
| 			proc, | ||||
| 			bytes.NewBuffer(file.Data), | ||||
| 		) | ||||
| 	} | ||||
|  | ||||
| 	return s.store.FileCreate(&model.File{ | ||||
| 		BuildID: proc.BuildID, | ||||
| 		ProcID:  proc.ID, | ||||
| @@ -261,19 +290,13 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	if build.Status == model.StatusPending { | ||||
| 		build.Status = model.StatusRunning | ||||
| 		build.Started = state.Started | ||||
| 		if err := s.store.UpdateBuild(build); err != nil { | ||||
| 			log.Printf("error: done: cannot update build_id %d state: %s", build.ID, err) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	proc.Started = state.Started | ||||
| 	proc.State = model.StatusRunning | ||||
| 	proc.Stopped = state.Finished | ||||
| 	proc.Error = state.Error | ||||
| 	proc.ExitCode = state.ExitCode | ||||
| 	proc.State = model.StatusSuccess | ||||
| 	if proc.ExitCode != 0 || proc.Error != "" { | ||||
| 		proc.State = model.StatusFailure | ||||
| 	} | ||||
| 	if err := s.store.ProcUpdate(proc); err != nil { | ||||
| 		log.Printf("error: done: cannot update proc_id %d state: %s", procID, err) | ||||
| 	} | ||||
| @@ -287,7 +310,7 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error { | ||||
| 	// TODO handle this error | ||||
| 	procs, _ := s.store.ProcList(build) | ||||
| 	for _, p := range procs { | ||||
| 		if !proc.Running() && p.PPID == proc.PID { | ||||
| 		if p.Running() && p.PPID == proc.PID { | ||||
| 			p.State = model.StatusSkipped | ||||
| 			if p.Started != 0 { | ||||
| 				p.State = model.StatusKilled | ||||
| @@ -297,12 +320,11 @@ func (s *RPC) Done(c context.Context, id string, state rpc.State) error { | ||||
| 				log.Printf("error: done: cannot update proc_id %d child state: %s", p.ID, err) | ||||
| 			} | ||||
| 		} | ||||
| 		if !proc.Running() && p.PPID == 0 { | ||||
| 		if !p.Running() && p.PPID == 0 { | ||||
| 			done = true | ||||
| 			if p.Failing() { | ||||
| 				status = model.StatusFailure | ||||
| 			} | ||||
| 			continue | ||||
| 		} | ||||
| 	} | ||||
| 	if done { | ||||
|   | ||||
| @@ -1,37 +1,42 @@ | ||||
| package datastore | ||||
|  | ||||
| // | ||||
| // import ( | ||||
| // 	"bytes" | ||||
| // 	"io" | ||||
| // 	"io/ioutil" | ||||
| // | ||||
| // 	"github.com/drone/drone/model" | ||||
| // 	"github.com/russross/meddler" | ||||
| // ) | ||||
| // | ||||
| // func (db *datastore) ReadLog(job *model.Job) (io.ReadCloser, error) { | ||||
| // 	var log = new(model.Log) | ||||
| // 	var err = meddler.QueryRow(db, log, rebind(logQuery), job.ID) | ||||
| // 	var buf = bytes.NewBuffer(log.Data) | ||||
| // 	return ioutil.NopCloser(buf), err | ||||
| // } | ||||
| // | ||||
| // func (db *datastore) WriteLog(job *model.Job, r io.Reader) error { | ||||
| // 	var log = new(model.Log) | ||||
| // 	var err = meddler.QueryRow(db, log, rebind(logQuery), job.ID) | ||||
| // 	if err != nil { | ||||
| // 		log = &model.Log{JobID: job.ID} | ||||
| // 	} | ||||
| // 	log.Data, _ = ioutil.ReadAll(r) | ||||
| // 	return meddler.Save(db, logTable, log) | ||||
| // } | ||||
| // | ||||
| // const logTable = "logs" | ||||
| // | ||||
| // const logQuery = ` | ||||
| // SELECT * | ||||
| // FROM logs | ||||
| // WHERE log_job_id=? | ||||
| // LIMIT 1 | ||||
| // ` | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io" | ||||
| 	"io/ioutil" | ||||
|  | ||||
| 	"github.com/drone/drone/model" | ||||
| 	"github.com/russross/meddler" | ||||
| ) | ||||
|  | ||||
| func (db *datastore) LogFind(proc *model.Proc) (io.ReadCloser, error) { | ||||
| 	var log = new(logData) | ||||
| 	var err = meddler.QueryRow(db, log, rebind(logQuery), proc.ID) | ||||
| 	var buf = bytes.NewBuffer(log.Data) | ||||
| 	return ioutil.NopCloser(buf), err | ||||
| } | ||||
|  | ||||
| func (db *datastore) LogSave(proc *model.Proc, r io.Reader) error { | ||||
| 	var log = new(logData) | ||||
| 	var err = meddler.QueryRow(db, log, rebind(logQuery), proc.ID) | ||||
| 	if err != nil { | ||||
| 		log = &logData{ProcID: proc.ID} | ||||
| 	} | ||||
| 	log.Data, _ = ioutil.ReadAll(r) | ||||
| 	return meddler.Save(db, logTable, log) | ||||
| } | ||||
|  | ||||
| type logData struct { | ||||
| 	ID     int64  `meddler:"log_id,pk"` | ||||
| 	ProcID int64  `meddler:"log_job_id"` | ||||
| 	Data   []byte `meddler:"log_data"` | ||||
| } | ||||
|  | ||||
| const logTable = "logs" | ||||
|  | ||||
| const logQuery = ` | ||||
| SELECT * | ||||
| FROM logs | ||||
| WHERE log_job_id=? | ||||
| LIMIT 1 | ||||
| ` | ||||
|   | ||||
| @@ -1,61 +1,60 @@ | ||||
| package datastore | ||||
|  | ||||
| // | ||||
| // import ( | ||||
| // 	"bytes" | ||||
| // 	"io/ioutil" | ||||
| // 	"testing" | ||||
| // | ||||
| // 	"github.com/drone/drone/model" | ||||
| // 	"github.com/franela/goblin" | ||||
| // ) | ||||
| // | ||||
| // func TestLogs(t *testing.T) { | ||||
| // 	db := openTest() | ||||
| // 	defer db.Close() | ||||
| // | ||||
| // 	s := From(db) | ||||
| // 	g := goblin.Goblin(t) | ||||
| // 	g.Describe("Logs", func() { | ||||
| // | ||||
| // 		// before each test be sure to purge the package | ||||
| // 		// table data from the database. | ||||
| // 		g.BeforeEach(func() { | ||||
| // 			db.Exec("DELETE FROM logs") | ||||
| // 		}) | ||||
| // | ||||
| // 		g.It("Should create a log", func() { | ||||
| // 			job := model.Job{ | ||||
| // 				ID: 1, | ||||
| // 			} | ||||
| // 			buf := bytes.NewBufferString("echo hi") | ||||
| // 			err := s.WriteLog(&job, buf) | ||||
| // 			g.Assert(err == nil).IsTrue() | ||||
| // | ||||
| // 			rc, err := s.ReadLog(&job) | ||||
| // 			g.Assert(err == nil).IsTrue() | ||||
| // 			defer rc.Close() | ||||
| // 			out, _ := ioutil.ReadAll(rc) | ||||
| // 			g.Assert(string(out)).Equal("echo hi") | ||||
| // 		}) | ||||
| // | ||||
| // 		g.It("Should update a log", func() { | ||||
| // 			job := model.Job{ | ||||
| // 				ID: 1, | ||||
| // 			} | ||||
| // 			buf1 := bytes.NewBufferString("echo hi") | ||||
| // 			buf2 := bytes.NewBufferString("echo allo?") | ||||
| // 			err1 := s.WriteLog(&job, buf1) | ||||
| // 			err2 := s.WriteLog(&job, buf2) | ||||
| // 			g.Assert(err1 == nil).IsTrue() | ||||
| // 			g.Assert(err2 == nil).IsTrue() | ||||
| // | ||||
| // 			rc, err := s.ReadLog(&job) | ||||
| // 			g.Assert(err == nil).IsTrue() | ||||
| // 			defer rc.Close() | ||||
| // 			out, _ := ioutil.ReadAll(rc) | ||||
| // 			g.Assert(string(out)).Equal("echo allo?") | ||||
| // 		}) | ||||
| // | ||||
| // 	}) | ||||
| // } | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	"io/ioutil" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/drone/drone/model" | ||||
| 	"github.com/franela/goblin" | ||||
| ) | ||||
|  | ||||
| func TestLogs(t *testing.T) { | ||||
| 	db := openTest() | ||||
| 	defer db.Close() | ||||
|  | ||||
| 	s := From(db) | ||||
| 	g := goblin.Goblin(t) | ||||
| 	g.Describe("Logs", func() { | ||||
|  | ||||
| 		// before each test be sure to purge the package | ||||
| 		// table data from the database. | ||||
| 		g.BeforeEach(func() { | ||||
| 			db.Exec("DELETE FROM logs") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should create a log", func() { | ||||
| 			proc := model.Proc{ | ||||
| 				ID: 1, | ||||
| 			} | ||||
| 			buf := bytes.NewBufferString("echo hi") | ||||
| 			err := s.LogSave(&proc, buf) | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
|  | ||||
| 			rc, err := s.LogFind(&proc) | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 			defer rc.Close() | ||||
| 			out, _ := ioutil.ReadAll(rc) | ||||
| 			g.Assert(string(out)).Equal("echo hi") | ||||
| 		}) | ||||
|  | ||||
| 		g.It("Should update a log", func() { | ||||
| 			proc := model.Proc{ | ||||
| 				ID: 1, | ||||
| 			} | ||||
| 			buf1 := bytes.NewBufferString("echo hi") | ||||
| 			buf2 := bytes.NewBufferString("echo allo?") | ||||
| 			err1 := s.LogSave(&proc, buf1) | ||||
| 			err2 := s.LogSave(&proc, buf2) | ||||
| 			g.Assert(err1 == nil).IsTrue() | ||||
| 			g.Assert(err2 == nil).IsTrue() | ||||
|  | ||||
| 			rc, err := s.LogFind(&proc) | ||||
| 			g.Assert(err == nil).IsTrue() | ||||
| 			defer rc.Close() | ||||
| 			out, _ := ioutil.ReadAll(rc) | ||||
| 			g.Assert(string(out)).Equal("echo allo?") | ||||
| 		}) | ||||
|  | ||||
| 	}) | ||||
| } | ||||
|   | ||||
| @@ -152,6 +152,9 @@ type Store interface { | ||||
| 	ProcCreate([]*model.Proc) error | ||||
| 	ProcUpdate(*model.Proc) error | ||||
|  | ||||
| 	LogFind(*model.Proc) (io.ReadCloser, error) | ||||
| 	LogSave(*model.Proc, io.Reader) error | ||||
|  | ||||
| 	FileList(*model.Build) ([]*model.File, error) | ||||
| 	FileFind(*model.Proc, string) (*model.File, error) | ||||
| 	FileRead(*model.Proc, string) (io.ReadCloser, error) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user