migration to discussed data model in #1066

This commit is contained in:
Brad Rydzewski 2015-06-22 20:45:08 -07:00
parent 2b269d0e54
commit e6cb22f190
35 changed files with 1560 additions and 1391 deletions

View file

@ -54,7 +54,7 @@ func main() {
}
log.Infof("Pulled and running build %s / %d",
w.Repo.FullName, w.Commit.Sequence)
w.Repo.FullName, w.Build.Number)
updater := &updater{}
runner_ := runner.Runner{Updater: updater}

View file

@ -17,18 +17,18 @@ import (
type updater struct{}
func (u *updater) SetCommit(user *common.User, r *common.Repo, c *common.Commit) error {
func (u *updater) SetBuild(user *common.User, r *common.Repo, b *common.Build) error {
path := fmt.Sprintf("/api/queue/push/%s", r.FullName)
return sendBackoff("POST", path, c, nil)
return sendBackoff("POST", path, b, nil)
}
func (u *updater) SetJob(r *common.Repo, c *common.Commit, j *common.Job) error {
path := fmt.Sprintf("/api/queue/push/%s/%v", r.FullName, c.Sequence)
func (u *updater) SetJob(r *common.Repo, b *common.Build, j *common.Job) error {
path := fmt.Sprintf("/api/queue/push/%s/%v", r.FullName, b.Number)
return sendBackoff("POST", path, j, nil)
}
func (u *updater) SetLogs(r *common.Repo, c *common.Commit, j *common.Job, rc io.ReadCloser) error {
path := fmt.Sprintf("/api/queue/push/%s/%v/%v", r.FullName, c.Sequence, j.Number)
func (u *updater) SetLogs(r *common.Repo, b *common.Build, j *common.Job, rc io.ReadCloser) error {
path := fmt.Sprintf("/api/queue/push/%s/%v/%v", r.FullName, b.Number, j.Number)
return sendBackoff("POST", path, rc, nil)
}

View file

@ -23,7 +23,7 @@ type CCProject struct {
WebURL string `xml:"webUrl,attr"`
}
func NewCC(r *types.Repo, c *types.Commit) *CCProjects {
func NewCC(r *types.Repo, b *types.Build) *CCProjects {
proj := &CCProject{
Name: r.Owner + "/" + r.Name,
WebURL: r.Self,
@ -34,16 +34,16 @@ func NewCC(r *types.Repo, c *types.Commit) *CCProjects {
// if the build is not currently running then
// we can return the latest build status.
if c.State != types.StatePending &&
c.State != types.StateRunning {
if b.Status != types.StatePending &&
b.Status != types.StateRunning {
proj.Activity = "Sleeping"
proj.LastBuildTime = time.Unix(c.Started, 0).Format(time.RFC3339)
proj.LastBuildLabel = strconv.Itoa(c.Sequence)
proj.LastBuildTime = time.Unix(b.Started, 0).Format(time.RFC3339)
proj.LastBuildLabel = strconv.Itoa(b.Number)
}
// ensure the last build state accepts a valid
// ccmenu enumeration
switch c.State {
switch b.Status {
case types.StateError, types.StateKilled:
proj.LastBuildStatus = "Exception"
case types.StateSuccess:

View file

@ -11,7 +11,7 @@ import (
type Work struct {
User *common.User `json:"user"`
Repo *common.Repo `json:"repo"`
Commit *common.Commit `json:"commit"`
Build *common.Build `json:"build"`
Keys *common.Keypair `json:"keypair"`
Netrc *common.Netrc `json:"netrc"`
Yaml []byte `json:"yaml"`

View file

@ -5,7 +5,6 @@ import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
@ -143,15 +142,9 @@ func (g *GitHub) Perm(u *common.User, owner, name string) (*common.Perm, error)
// Script fetches the build script (.drone.yml) from the remote
// repository and returns in string format.
func (g *GitHub) Script(u *common.User, r *common.Repo, c *common.Commit) ([]byte, error) {
func (g *GitHub) Script(u *common.User, r *common.Repo, b *common.Build) ([]byte, error) {
client := NewClient(g.API, u.Token, g.SkipVerify)
var sha string
if len(c.SourceSha) == 0 {
sha = c.Sha
} else {
sha = c.SourceSha
}
return GetFile(client, r.Owner, r.Name, ".drone.yml", sha)
return GetFile(client, r.Owner, r.Name, ".drone.yml", b.Commit.Sha)
}
// Netrc returns a .netrc file that can be used to clone
@ -209,19 +202,19 @@ func (g *GitHub) Deactivate(u *common.User, r *common.Repo, link string) error {
return DeleteHook(client, r.Owner, r.Name, link)
}
func (g *GitHub) Status(u *common.User, r *common.Repo, c *common.Commit) error {
func (g *GitHub) Status(u *common.User, r *common.Repo, b *common.Build) error {
client := NewClient(g.API, u.Token, g.SkipVerify)
link := fmt.Sprintf("%s/%v", r.Self, c.Sequence)
status := getStatus(c.State)
desc := getDesc(c.State)
link := fmt.Sprintf("%s/%v", r.Self, b.Number)
status := getStatus(b.Status)
desc := getDesc(b.Status)
data := github.RepoStatus{
Context: github.String("Drone"),
State: github.String(status),
Description: github.String(desc),
TargetURL: github.String(link),
}
_, _, err := client.Repositories.CreateStatus(r.Owner, r.Name, c.SourceSha, &data)
_, _, err := client.Repositories.CreateStatus(r.Owner, r.Name, b.Commit.Sha, &data)
return err
}
@ -270,10 +263,10 @@ func (g *GitHub) push(r *http.Request) (*common.Hook, error) {
commit.Branch = strings.Replace(commit.Ref, "refs/heads/", "", -1)
commit.Message = hook.Head.Message
commit.Timestamp = hook.Head.Timestamp
commit.Author = hook.Head.Author.Username
// commit.Author.Name = hook.Head.Author.Name
// commit.Author.Email = hook.Head.Author.Email
// commit.Author.Login = hook.Head.Author.Username
commit.Author = &common.Author{}
commit.Author.Email = hook.Head.Author.Email
commit.Author.Login = hook.Head.Author.Username
commit.Remote = hook.Repo.CloneURL
// we should ignore github pages
if commit.Ref == "refs/heads/gh-pages" {
@ -318,19 +311,31 @@ func (g *GitHub) pullRequest(r *http.Request) (*common.Hook, error) {
}
c := &common.Commit{}
c.PullRequest = strconv.Itoa(*hook.PullRequest.Number)
c.Message = *hook.PullRequest.Title
c.Sha = *hook.PullRequest.Base.SHA
c.Ref = *hook.PullRequest.Base.Ref
c.Ref = fmt.Sprintf("refs/pull/%s/merge", c.PullRequest)
c.Branch = *hook.PullRequest.Base.Ref
c.Sha = *hook.PullRequest.Head.SHA
c.Ref = *hook.PullRequest.Head.Ref
c.Ref = fmt.Sprintf("refs/pull/%s/merge", *hook.PullRequest.Number)
c.Branch = *hook.PullRequest.Head.Ref
c.Timestamp = time.Now().UTC().Format("2006-01-02 15:04:05.000000000 +0000 MST")
c.Author = *hook.PullRequest.Base.User.Login
c.SourceRemote = *hook.PullRequest.Head.Repo.CloneURL
c.SourceBranch = *hook.PullRequest.Head.Ref
c.SourceSha = *hook.PullRequest.Head.SHA
c.Remote = *hook.PullRequest.Head.Repo.CloneURL
c.Author = &common.Author{}
c.Author.Login = *hook.PullRequest.Head.User.Login
// Author.Email
// Message
return &common.Hook{Repo: repo, Commit: c}, nil
pr := &common.PullRequest{}
pr.Number = *hook.PullRequest.Number
pr.Title = *hook.PullRequest.Title
pr.Base = &common.Commit{}
pr.Base.Sha = *hook.PullRequest.Base.SHA
pr.Base.Ref = *hook.PullRequest.Base.Ref
pr.Base.Remote = *hook.PullRequest.Base.Repo.CloneURL
// Branch
// Message
// Timestamp
// Author.Login
// Author.Email
return &common.Hook{Repo: repo, Commit: c, PullRequest: pr}, nil
}
type pushHook struct {

View file

@ -23,11 +23,11 @@ type Remote interface {
// Script fetches the build script (.drone.yml) from the remote
// repository and returns in string format.
Script(u *common.User, r *common.Repo, c *common.Commit) ([]byte, error)
Script(u *common.User, r *common.Repo, b *common.Build) ([]byte, error)
// Status sends the commit status to the remote system.
// An example would be the GitHub pull request status.
Status(u *common.User, r *common.Repo, c *common.Commit) error
Status(u *common.User, r *common.Repo, b *common.Build) error
// Netrc returns a .netrc file that can be used to clone
// private repositories from a remote system.

View file

@ -53,10 +53,10 @@ func (r *Runner) Run(w *queue.Work) error {
// if any part of the commit fails and leaves
// behind orphan sub-builds we need to cleanup
// after ourselves.
if w.Commit.State == types.StateRunning {
if w.Build.Status == types.StateRunning {
// if any tasks are running or pending
// we should mark them as complete.
for _, b := range w.Commit.Builds {
for _, b := range w.Build.Jobs {
if b.Status == types.StateRunning {
b.Status = types.StateError
b.Finished = time.Now().UTC().Unix()
@ -68,23 +68,23 @@ func (r *Runner) Run(w *queue.Work) error {
b.Finished = time.Now().UTC().Unix()
b.ExitCode = 255
}
r.SetJob(w.Repo, w.Commit, b)
r.SetJob(w.Repo, w.Build, b)
}
// must populate build start
if w.Commit.Started == 0 {
w.Commit.Started = time.Now().UTC().Unix()
if w.Build.Started == 0 {
w.Build.Started = time.Now().UTC().Unix()
}
// mark the build as complete (with error)
w.Commit.State = types.StateError
w.Commit.Finished = time.Now().UTC().Unix()
r.SetCommit(w.User, w.Repo, w.Commit)
w.Build.Status = types.StateError
w.Build.Finished = time.Now().UTC().Unix()
r.SetBuild(w.User, w.Repo, w.Build)
}
}()
// marks the build as running
w.Commit.Started = time.Now().UTC().Unix()
w.Commit.State = types.StateRunning
err := r.SetCommit(w.User, w.Repo, w.Commit)
w.Build.Started = time.Now().UTC().Unix()
w.Build.Status = types.StateRunning
err := r.SetBuild(w.User, w.Repo, w.Build)
if err != nil {
return err
}
@ -99,19 +99,19 @@ func (r *Runner) Run(w *queue.Work) error {
// loop through and execute the build and
// clone steps for each build job.
for _, job := range w.Commit.Builds {
for _, job := range w.Build.Jobs {
// marks the task as running
job.Status = types.StateRunning
job.Started = time.Now().UTC().Unix()
err = r.SetJob(w.Repo, w.Commit, job)
err = r.SetJob(w.Repo, w.Build, job)
if err != nil {
return err
}
work := &work{
Repo: w.Repo,
Commit: w.Commit,
Build: w.Build,
Keys: w.Keys,
Netrc: w.Netrc,
Yaml: w.Yaml,
@ -127,7 +127,7 @@ func (r *Runner) Run(w *queue.Work) error {
worker := newWorkerTimeout(client, w.Repo.Timeout)
workers = append(workers, worker)
cname := cname(job)
pullrequest := (w.Commit.PullRequest != "")
pullrequest := (w.Build.PullRequest != nil)
state, builderr := worker.Build(cname, in, pullrequest)
switch {
@ -156,14 +156,14 @@ func (r *Runner) Run(w *queue.Work) error {
defer rc.Close()
docker.StdCopy(&buf, &buf, rc)
}
err = r.SetLogs(w.Repo, w.Commit, job, ioutil.NopCloser(&buf))
err = r.SetLogs(w.Repo, w.Build, job, ioutil.NopCloser(&buf))
if err != nil {
return err
}
// update the task in the datastore
job.Finished = time.Now().UTC().Unix()
err = r.SetJob(w.Repo, w.Commit, job)
err = r.SetJob(w.Repo, w.Build, job)
if err != nil {
return err
}
@ -171,24 +171,24 @@ func (r *Runner) Run(w *queue.Work) error {
// update the build state if any of the sub-tasks
// had a non-success status
w.Commit.State = types.StateSuccess
for _, job := range w.Commit.Builds {
w.Build.Status = types.StateSuccess
for _, job := range w.Build.Jobs {
if job.Status != types.StateSuccess {
w.Commit.State = job.Status
w.Build.Status = job.Status
break
}
}
err = r.SetCommit(w.User, w.Repo, w.Commit)
err = r.SetBuild(w.User, w.Repo, w.Build)
if err != nil {
return err
}
// loop through and execute the notifications and
// the destroy all containers afterward.
for i, job := range w.Commit.Builds {
for i, job := range w.Build.Jobs {
work := &work{
Repo: w.Repo,
Commit: w.Commit,
Build: w.Build,
Keys: w.Keys,
Netrc: w.Netrc,
Yaml: w.Yaml,

View file

@ -12,9 +12,9 @@ import (
)
type Updater interface {
SetCommit(*types.User, *types.Repo, *types.Commit) error
SetJob(*types.Repo, *types.Commit, *types.Job) error
SetLogs(*types.Repo, *types.Commit, *types.Job, io.ReadCloser) error
SetBuild(*types.User, *types.Repo, *types.Build) error
SetJob(*types.Repo, *types.Build, *types.Job) error
SetLogs(*types.Repo, *types.Build, *types.Job, io.ReadCloser) error
}
// NewUpdater returns an implementation of the Updater interface
@ -29,8 +29,8 @@ type updater struct {
remote remote.Remote
}
func (u *updater) SetCommit(user *types.User, r *types.Repo, c *types.Commit) error {
err := u.store.SetCommit(c)
func (u *updater) SetBuild(user *types.User, r *types.Repo, c *types.Build) error {
err := u.store.SetBuild(c)
if err != nil {
return err
}
@ -44,8 +44,8 @@ func (u *updater) SetCommit(user *types.User, r *types.Repo, c *types.Commit) er
// a remote agent won't have the embedded
// build list. we should probably just rethink
// the messaging instead of this hack.
if c.Builds == nil || len(c.Builds) == 0 {
c.Builds, _ = u.store.JobList(c)
if c.Jobs == nil || len(c.Jobs) == 0 {
c.Jobs, _ = u.store.JobList(c)
}
msg, err := json.Marshal(c)
@ -61,7 +61,7 @@ func (u *updater) SetCommit(user *types.User, r *types.Repo, c *types.Commit) er
return nil
}
func (u *updater) SetJob(r *types.Repo, c *types.Commit, j *types.Job) error {
func (u *updater) SetJob(r *types.Repo, c *types.Build, j *types.Job) error {
err := u.store.SetJob(j)
if err != nil {
return err
@ -71,8 +71,8 @@ func (u *updater) SetJob(r *types.Repo, c *types.Commit, j *types.Job) error {
// a remote agent won't have the embedded
// build list. we should probably just rethink
// the messaging instead of this hack.
if c.Builds == nil || len(c.Builds) == 0 {
c.Builds, _ = u.store.JobList(c)
if c.Jobs == nil || len(c.Jobs) == 0 {
c.Jobs, _ = u.store.JobList(c)
}
msg, err := json.Marshal(c)
@ -88,7 +88,7 @@ func (u *updater) SetJob(r *types.Repo, c *types.Commit, j *types.Job) error {
return nil
}
func (u *updater) SetLogs(r *types.Repo, c *types.Commit, j *types.Job, rc io.ReadCloser) error {
path := fmt.Sprintf("/logs/%s/%v/%v", r.FullName, c.Sequence, j.Number)
func (u *updater) SetLogs(r *types.Repo, c *types.Build, j *types.Job, rc io.ReadCloser) error {
path := fmt.Sprintf("/logs/%s/%v/%v", r.FullName, c.Number, j.Number)
return u.store.SetBlobReader(path, rc)
}

View file

@ -53,7 +53,7 @@ var (
type work struct {
Repo *types.Repo `json:"repo"`
Commit *types.Commit `json:"commit"`
Build *types.Build `json:"build"`
Job *types.Job `json:"job"`
Keys *types.Keypair `json:"keys"`
Netrc *types.Netrc `json:"netrc"`

View file

@ -16,7 +16,7 @@ type Runner interface {
// Updater defines a set of functions that are required for
// the runner to sent Drone updates during a build.
type Updater interface {
SetCommit(*types.User, *types.Repo, *types.Commit) error
SetJob(*types.Repo, *types.Commit, *types.Job) error
SetLogs(*types.Repo, *types.Commit, *types.Job, io.ReadCloser) error
SetBuild(*types.User, *types.Repo, *types.Build) error
SetJob(*types.Repo, *types.Build, *types.Job) error
SetLogs(*types.Repo, *types.Build, *types.Job, io.ReadCloser) error
}

View file

@ -36,13 +36,13 @@ func GetBadge(c *gin.Context) {
// if no commit was found then display
// the 'none' badge, instead of throwing
// an error response
commit, err := store.CommitLast(repo, branch)
build, err := store.BuildLast(repo, branch)
if err != nil {
c.Writer.Write(badgeNone)
return
}
switch commit.State {
switch build.Status {
case common.StateSuccess:
c.Writer.Write(badgeSuccess)
case common.StateFailure:
@ -66,7 +66,7 @@ func GetBadge(c *gin.Context) {
func GetCC(c *gin.Context) {
store := ToDatastore(c)
repo := ToRepo(c)
list, err := store.CommitList(repo, 1, 0)
list, err := store.BuildList(repo, 1, 0)
if err != nil || len(list) == 0 {
c.AbortWithStatus(404)
return

View file

@ -27,15 +27,15 @@ func GetCommit(c *gin.Context) {
c.Fail(400, err)
return
}
commit, err := store.CommitSeq(repo, num)
build, err := store.BuildNumber(repo, num)
if err != nil {
c.Fail(404, err)
}
commit.Builds, err = store.JobList(commit)
build.Jobs, err = store.JobList(build)
if err != nil {
c.Fail(404, err)
} else {
c.JSON(200, commit)
c.JSON(200, build)
}
}
@ -47,11 +47,11 @@ func GetCommit(c *gin.Context) {
func GetCommits(c *gin.Context) {
store := ToDatastore(c)
repo := ToRepo(c)
commits, err := store.CommitList(repo, 20, 0)
builds, err := store.BuildList(repo, 20, 0)
if err != nil {
c.Fail(404, err)
} else {
c.JSON(200, commits)
c.JSON(200, builds)
}
}
@ -65,10 +65,10 @@ func GetLogs(c *gin.Context) {
store := ToDatastore(c)
repo := ToRepo(c)
full, _ := strconv.ParseBool(c.Params.ByName("full"))
commit, _ := strconv.Atoi(c.Params.ByName("number"))
build, _ := strconv.Atoi(c.Params.ByName("task"))
build, _ := strconv.Atoi(c.Params.ByName("number"))
job, _ := strconv.Atoi(c.Params.ByName("task"))
path := fmt.Sprintf("/logs/%s/%v/%v", repo.FullName, commit, build)
path := fmt.Sprintf("/logs/%s/%v/%v", repo.FullName, build, job)
r, err := store.GetBlobReader(path)
if err != nil {
c.Fail(404, err)
@ -121,12 +121,12 @@ func RunBuild(c *gin.Context) {
c.Fail(400, err)
return
}
commit, err := store.CommitSeq(repo, num)
build, err := store.BuildNumber(repo, num)
if err != nil {
c.Fail(404, err)
return
}
commit.Builds, err = store.JobList(commit)
build.Jobs, err = store.JobList(build)
if err != nil {
c.Fail(404, err)
return
@ -139,22 +139,22 @@ func RunBuild(c *gin.Context) {
}
// must not restart a running build
if commit.State == common.StatePending || commit.State == common.StateRunning {
if build.Status == common.StatePending || build.Status == common.StateRunning {
c.AbortWithStatus(409)
return
}
commit.State = common.StatePending
commit.Started = 0
commit.Finished = 0
for _, job := range commit.Builds {
build.Status = common.StatePending
build.Started = 0
build.Finished = 0
for _, job := range build.Jobs {
job.Status = common.StatePending
job.Started = 0
job.Finished = 0
job.ExitCode = 0
}
err = store.SetCommit(commit)
err = store.SetBuild(build)
if err != nil {
c.Fail(500, err)
return
@ -167,7 +167,7 @@ func RunBuild(c *gin.Context) {
}
// featch the .drone.yml file from the database
raw, err := remote.Script(user, repo, commit)
raw, err := remote.Script(user, repo, build)
if err != nil {
c.Fail(404, err)
return
@ -178,12 +178,12 @@ func RunBuild(c *gin.Context) {
raw = []byte(inject.InjectSafe(string(raw), repo.Params))
}
c.JSON(202, commit)
c.JSON(202, build)
queue_.Publish(&queue.Work{
User: user,
Repo: repo,
Commit: commit,
Build: build,
Keys: repo.Keys,
Netrc: netrc,
Yaml: raw,
@ -206,19 +206,19 @@ func KillBuild(c *gin.Context) {
c.Fail(400, err)
return
}
commit, err := store.CommitSeq(repo, num)
build, err := store.BuildNumber(repo, num)
if err != nil {
c.Fail(404, err)
return
}
commit.Builds, err = store.JobList(commit)
build.Jobs, err = store.JobList(build)
if err != nil {
c.Fail(404, err)
return
}
// must not restart a running build
if commit.State != common.StatePending && commit.State != common.StateRunning {
if build.Status != common.StatePending && build.Status != common.StateRunning {
c.Fail(409, err)
return
}
@ -228,32 +228,32 @@ func KillBuild(c *gin.Context) {
// TODO(bradrydzewski) this could yield a race condition
// because other threads may also be accessing these items.
for _, item := range queue.Items() {
if item.Repo.FullName == repo.FullName && item.Commit.Sequence == commit.Sequence {
if item.Repo.FullName == repo.FullName && item.Build.Number == build.Number {
queue.Remove(item)
break
}
}
commit.State = common.StateKilled
commit.Finished = time.Now().Unix()
if commit.Started == 0 {
commit.Started = commit.Finished
build.Status = common.StateKilled
build.Finished = time.Now().Unix()
if build.Started == 0 {
build.Started = build.Finished
}
for _, job := range commit.Builds {
for _, job := range build.Jobs {
if job.Status != common.StatePending && job.Status != common.StateRunning {
continue
}
job.Status = common.StateKilled
job.Started = commit.Started
job.Finished = commit.Finished
job.Started = build.Started
job.Finished = build.Finished
}
err = store.SetCommit(commit)
err = store.SetBuild(build)
if err != nil {
c.Fail(500, err)
return
}
for _, job := range commit.Builds {
for _, job := range build.Jobs {
runner.Cancel(job)
}
// // get the agent from the repository so we can
@ -272,5 +272,5 @@ func KillBuild(c *gin.Context) {
// }
// defer resp.Body.Close()
c.JSON(200, commit)
c.JSON(200, build)
}

View file

@ -68,11 +68,11 @@ func PostHook(c *gin.Context) {
log.Warnf("ignoring hook. repo %s has no owner.", repo.FullName)
c.Writer.WriteHeader(204)
return
case !repo.Hooks.Push && hook.Commit.PullRequest != "":
case !repo.Hooks.Push && hook.PullRequest != nil:
log.Infof("ignoring hook. repo %s is disabled.", repo.FullName)
c.Writer.WriteHeader(204)
return
case !repo.Hooks.PullRequest && hook.Commit.PullRequest == "":
case !repo.Hooks.PullRequest && hook.PullRequest == nil:
log.Warnf("ignoring hook. repo %s is disabled for pull requests.", repo.FullName)
c.Writer.WriteHeader(204)
return
@ -85,12 +85,14 @@ func PostHook(c *gin.Context) {
return
}
commit := hook.Commit
commit.State = common.StatePending
commit.RepoID = repo.ID
build := &common.Build{}
build.Commit = hook.Commit
build.PullRequest = hook.PullRequest
build.Status = common.StatePending
build.RepoID = repo.ID
// featch the .drone.yml file from the database
raw, err := remote.Script(user, repo, commit)
raw, err := remote.Script(user, repo, build)
if err != nil {
log.Errorf("failure to get .drone.yml for %s. %s", repo.FullName, err)
c.Fail(404, err)
@ -110,8 +112,8 @@ func PostHook(c *gin.Context) {
axes = append(axes, matrix.Axis{})
}
for num, axis := range axes {
commit.Builds = append(commit.Builds, &common.Job{
BuildID: commit.ID,
build.Jobs = append(build.Jobs, &common.Job{
BuildID: build.ID,
Number: num + 1,
Status: common.StatePending,
Environment: axis,
@ -127,30 +129,30 @@ func PostHook(c *gin.Context) {
// verify the branches can be built vs skipped
when, _ := parser.ParseCondition(string(raw))
if commit.PullRequest != "" && when != nil && !when.MatchBranch(commit.Branch) {
log.Infof("ignoring hook. yaml file excludes repo and branch %s %s", repo.FullName, commit.Branch)
if build.PullRequest != nil && when != nil && !when.MatchBranch(build.Commit.Branch) {
log.Infof("ignoring hook. yaml file excludes repo and branch %s %s", repo.FullName, build.Commit.Branch)
c.AbortWithStatus(200)
return
}
err = store.AddCommit(commit)
err = store.AddBuild(build)
if err != nil {
log.Errorf("failure to save commit for %s. %s", repo.FullName, err)
c.Fail(500, err)
return
}
c.JSON(200, commit)
c.JSON(200, build)
err = remote.Status(user, repo, commit)
err = remote.Status(user, repo, build)
if err != nil {
log.Errorf("error setting commit status for %s/%d", repo.FullName, commit.Sequence)
log.Errorf("error setting commit status for %s/%d", repo.FullName, build.Number)
}
queue_.Publish(&queue.Work{
User: user,
Repo: repo,
Commit: commit,
Build: build,
Keys: repo.Keys,
Netrc: netrc,
Yaml: raw,

View file

@ -35,13 +35,13 @@ func PollBuild(c *gin.Context) {
}
// persist the relationship between agent and commit.
err = store.SetAgent(work.Commit, addr)
err = store.SetAgent(work.Build, addr)
if err != nil {
// note the we are ignoring and just logging the error here.
// we consider this an acceptible failure because it doesn't
// impact anything other than live-streaming output.
log.Errorf("unable to store the agent address %s for build %s %v",
addr, work.Repo.FullName, work.Commit.Sequence)
addr, work.Repo.FullName, work.Build.Number)
}
c.JSON(200, work)
@ -55,7 +55,7 @@ func PushCommit(c *gin.Context) {
store := ToDatastore(c)
repo := ToRepo(c)
in := &common.Commit{}
in := &common.Build{}
if !c.BindWith(in, binding.JSON) {
return
}
@ -64,18 +64,18 @@ func PushCommit(c *gin.Context) {
c.Fail(404, err)
return
}
commit, err := store.CommitSeq(repo, in.Sequence)
build, err := store.BuildNumber(repo, in.Number)
if err != nil {
c.Fail(404, err)
return
}
commit.Started = in.Started
commit.Finished = in.Finished
commit.State = in.State
build.Started = in.Started
build.Finished = in.Finished
build.Status = in.Status
updater := ToUpdater(c)
err = updater.SetCommit(user, repo, commit)
err = updater.SetBuild(user, repo, build)
if err != nil {
c.Fail(500, err)
return
@ -94,12 +94,12 @@ func PushBuild(c *gin.Context) {
return
}
commit, err := store.CommitSeq(repo, cnum)
build, err := store.BuildNumber(repo, cnum)
if err != nil {
c.Fail(404, err)
return
}
job, err := store.JobNumber(commit, in.Number)
job, err := store.JobNumber(build, in.Number)
if err != nil {
c.Fail(404, err)
return
@ -111,7 +111,7 @@ func PushBuild(c *gin.Context) {
job.Status = in.Status
updater := ToUpdater(c)
err = updater.SetJob(repo, commit, job)
err = updater.SetJob(repo, build, job)
if err != nil {
c.Fail(500, err)
return
@ -126,18 +126,18 @@ func PushLogs(c *gin.Context) {
cnum, _ := strconv.Atoi(c.Params.ByName("commit"))
bnum, _ := strconv.Atoi(c.Params.ByName("build"))
commit, err := store.CommitSeq(repo, cnum)
build, err := store.BuildNumber(repo, cnum)
if err != nil {
c.Fail(404, err)
return
}
job, err := store.JobNumber(commit, bnum)
job, err := store.JobNumber(build, bnum)
if err != nil {
c.Fail(404, err)
return
}
updater := ToUpdater(c)
err = updater.SetLogs(repo, commit, job, c.Request.Body)
err = updater.SetLogs(repo, build, job, c.Request.Body)
if err != nil {
c.Fail(500, err)
return

View file

@ -60,12 +60,12 @@ func GetStream(c *gin.Context) {
c.Writer.Header().Set("Content-Type", "text/event-stream")
commit, err := store.CommitSeq(repo, commitseq)
build, err := store.BuildNumber(repo, commitseq)
if err != nil {
c.Fail(404, err)
return
}
job, err := store.JobNumber(commit, jobnum)
job, err := store.JobNumber(build, jobnum)
if err != nil {
c.Fail(404, err)
return
@ -77,7 +77,7 @@ func GetStream(c *gin.Context) {
// we'll proxy the build output directly to the
// remote Docker client, through the agent.
if conf.Agents.Secret != "" {
addr, err := store.Agent(commit)
addr, err := store.Agent(build)
if err != nil {
c.Fail(500, err)
return

View file

@ -15,8 +15,8 @@ func NewAgentstore(db *sql.DB) *Agentstore {
}
// Agent returns an agent by ID.
func (db *Agentstore) Agent(commit *types.Commit) (string, error) {
agent, err := getAgent(db, rebind(stmtAgentSelectAgentCommit), commit.ID)
func (db *Agentstore) Agent(build *types.Build) (string, error) {
agent, err := getAgent(db, rebind(stmtAgentSelectAgentCommit), build.ID)
if err != nil {
return "", err
}
@ -24,13 +24,13 @@ func (db *Agentstore) Agent(commit *types.Commit) (string, error) {
}
// SetAgent updates an agent in the datastore.
func (db *Agentstore) SetAgent(commit *types.Commit, addr string) error {
agent := Agent{Addr: addr, CommitID: commit.ID}
func (db *Agentstore) SetAgent(build *types.Build, addr string) error {
agent := Agent{Addr: addr, BuildID: build.ID}
return createAgent(db, rebind(stmtAgentInsert), &agent)
}
type Agent struct {
ID int64
Addr string
CommitID int64 `sql:"unique:ux_agent_commit"`
ID int64
Addr string
BuildID int64 `sql:"unique:ux_agent_build"`
}

View file

@ -35,7 +35,7 @@ func createAgent(db agentDB, query string, v *Agent) error {
var v0 string
var v1 int64
v0 = v.Addr
v1 = v.CommitID
v1 = v.BuildID
res, err := db.Exec(query,
&v0,
@ -55,7 +55,7 @@ func updateAgent(db agentDB, query string, v *Agent) error {
var v2 int64
v0 = v.ID
v1 = v.Addr
v2 = v.CommitID
v2 = v.BuildID
_, err := db.Exec(query,
&v1,
@ -82,7 +82,7 @@ func scanAgent(row *sql.Row) (*Agent, error) {
v := &Agent{}
v.ID = v0
v.Addr = v1
v.CommitID = v2
v.BuildID = v2
return v, nil
}
@ -106,7 +106,7 @@ func scanAgents(rows *sql.Rows) ([]*Agent, error) {
v := &Agent{}
v.ID = v0
v.Addr = v1
v.CommitID = v2
v.BuildID = v2
vv = append(vv, v)
}
return vv, rows.Err()
@ -116,7 +116,7 @@ const stmtAgentSelectList = `
SELECT
agent_id
,agent_addr
,agent_commit_id
,agent_build_id
FROM agents
`

View file

@ -6,35 +6,136 @@ import (
"github.com/drone/drone/pkg/types"
)
type Jobstore struct {
type Buildstore struct {
*sql.DB
}
func NewJobstore(db *sql.DB) *Jobstore {
return &Jobstore{db}
func NewBuildstore(db *sql.DB) *Buildstore {
return &Buildstore{db}
}
// Job returns a Job by ID.
func (db *Jobstore) Job(id int64) (*types.Job, error) {
return getJob(db, rebind(stmtJobSelect), id)
// Build gets a build by ID
func (db *Buildstore) Build(id int64) (*types.Build, error) {
return getBuild(db, rebind(stmtBuildSelect), id)
}
// JobNumber returns a job by sequence number.
func (db *Jobstore) JobNumber(commit *types.Commit, seq int) (*types.Job, error) {
return getJob(db, rebind(stmtJobSelectBuildNumber), commit.ID, seq)
// BuildNumber gets the specified build number for the
// named repository and build number
func (db *Buildstore) BuildNumber(repo *types.Repo, seq int) (*types.Build, error) {
return getBuild(db, rebind(stmtBuildSelectBuildNumber), repo.ID, seq)
}
// JobList returns a list of all build jobs
func (db *Jobstore) JobList(commit *types.Commit) ([]*types.Job, error) {
return getJobs(db, rebind(stmtJobSelectJobBuildId), commit.ID)
// BuildLast gets the last executed build for the
// named repository.
func (db *Buildstore) BuildLast(repo *types.Repo, branch string) (*types.Build, error) {
return getBuild(db, rebind(buildLastQuery), repo.ID, branch)
}
// SetJob updates an existing build job.
func (db *Jobstore) SetJob(job *types.Job) error {
return updateJob(db, rebind(stmtJobUpdate), job)
// BuildList gets a list of recent builds for the
// named repository.
func (db *Buildstore) BuildList(repo *types.Repo, limit, offset int) ([]*types.Build, error) {
return getBuilds(db, rebind(buildListQuery), repo.ID, limit, offset)
}
// AddJob inserts a build job.
func (db *Jobstore) AddJob(job *types.Job) error {
return createJob(db, rebind(stmtJobInsert), job)
// AddBuild inserts a new build in the datastore.
func (db *Buildstore) AddBuild(build *types.Build) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
// extract the next build number from the database
row := tx.QueryRow(rebind(buildNumberLast), build.RepoID)
if row != nil {
row.Scan(&build.Number)
}
build.Number = build.Number + 1 // increment
err = createBuild(tx, rebind(stmtBuildInsert), build)
if err != nil {
return err
}
for _, job := range build.Jobs {
job.BuildID = build.ID
err := createJob(tx, rebind(stmtJobInsert), job)
if err != nil {
return err
}
}
return tx.Commit()
}
// SetBuild updates an existing build and build jobs.
func (db *Buildstore) SetBuild(build *types.Build) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
err = updateBuild(tx, rebind(stmtBuildUpdate), build)
if err != nil {
return err
}
for _, job := range build.Jobs {
err = updateJob(tx, rebind(stmtJobUpdate), job)
if err != nil {
return err
}
}
return tx.Commit()
}
// KillBuilds updates all pending or started builds
// in the datastore settings the status to killed.
func (db *Buildstore) KillBuilds() error {
var _, err1 = db.Exec(rebind(buildKillStmt))
if err1 != nil {
return err1
}
var _, err2 = db.Exec(rebind(jobKillStmt))
return err2
}
// SQL query to retrieve the latest builds across all branches.
const buildListQuery = `
SELECT *
FROM builds
WHERE build_repo_id = ?
ORDER BY build_number DESC
LIMIT ? OFFSET ?
`
// SQL query to retrieve the most recent build.
// TODO exclude pull requests
const buildLastQuery = `
SELECT *
FROM builds
WHERE build_repo_id = ?
AND build_commit_branch = ?
ORDER BY build_number DESC
LIMIT 1
`
// SQL statement to cancel all running builds.
const buildKillStmt = `
UPDATE builds SET build_status = 'killed'
WHERE build_status IN ('pending', 'running');
`
// SQL statement to cancel all running build jobs.
const jobKillStmt = `
UPDATE jobs SET job_status = 'killed'
WHERE job_status IN ('pending', 'running');
`
// SQL statement to retrieve the latest sequential
// build number for a build
const buildNumberLast = `
SELECT MAX(build_number)
FROM builds
WHERE build_repo_id = ?
`

View file

@ -13,41 +13,83 @@ import (
var _ = json.Marshal
// generic database interface, matching both *sql.Db and *sql.Tx
type jobDB interface {
type buildDB interface {
Exec(query string, args ...interface{}) (sql.Result, error)
Query(query string, args ...interface{}) (*sql.Rows, error)
QueryRow(query string, args ...interface{}) *sql.Row
}
func getJob(db jobDB, query string, args ...interface{}) (*Job, error) {
func getBuild(db buildDB, query string, args ...interface{}) (*Build, error) {
row := db.QueryRow(query, args...)
return scanJob(row)
return scanBuild(row)
}
func getJobs(db jobDB, query string, args ...interface{}) ([]*Job, error) {
func getBuilds(db buildDB, query string, args ...interface{}) ([]*Build, error) {
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
return scanJobs(rows)
return scanBuilds(rows)
}
func createJob(db jobDB, query string, v *Job) error {
func createBuild(db buildDB, query string, v *Build) error {
var v0 int64
var v1 int
var v2 string
var v3 int
var v3 int64
var v4 int64
var v5 int64
var v6 []byte
v0 = v.BuildID
var v5 string
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 int
var v14 string
var v15 string
var v16 string
var v17 string
var v18 string
var v19 string
var v20 string
var v21 string
var v22 string
v0 = v.RepoID
v1 = v.Number
v2 = v.Status
v3 = v.ExitCode
v4 = v.Started
v5 = v.Finished
v6, _ = json.Marshal(v.Environment)
v3 = v.Started
v4 = v.Finished
if v.Commit != nil {
v5 = v.Commit.Sha
v6 = v.Commit.Ref
v7 = v.Commit.Branch
v8 = v.Commit.Message
v9 = v.Commit.Timestamp
v10 = v.Commit.Remote
if v.Commit.Author != nil {
v11 = v.Commit.Author.Login
v12 = v.Commit.Author.Email
}
}
if v.PullRequest != nil {
v13 = v.PullRequest.Number
v14 = v.PullRequest.Title
if v.PullRequest.Base != nil {
v15 = v.PullRequest.Base.Sha
v16 = v.PullRequest.Base.Ref
v17 = v.PullRequest.Base.Branch
v18 = v.PullRequest.Base.Message
v19 = v.PullRequest.Base.Timestamp
v20 = v.PullRequest.Base.Remote
if v.PullRequest.Base.Author != nil {
v21 = v.PullRequest.Base.Author.Login
v22 = v.PullRequest.Base.Author.Email
}
}
}
res, err := db.Exec(query,
&v0,
@ -57,6 +99,22 @@ func createJob(db jobDB, query string, v *Job) error {
&v4,
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
&v19,
&v20,
&v21,
&v22,
)
if err != nil {
return err
@ -66,23 +124,65 @@ func createJob(db jobDB, query string, v *Job) error {
return err
}
func updateJob(db jobDB, query string, v *Job) error {
func updateBuild(db buildDB, query string, v *Build) error {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int
var v4 int64
var v5 int64
var v6 int64
var v7 []byte
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 int
var v15 string
var v16 string
var v17 string
var v18 string
var v19 string
var v20 string
var v21 string
var v22 string
var v23 string
v0 = v.ID
v1 = v.BuildID
v1 = v.RepoID
v2 = v.Number
v3 = v.Status
v4 = v.ExitCode
v5 = v.Started
v6 = v.Finished
v7, _ = json.Marshal(v.Environment)
v4 = v.Started
v5 = v.Finished
if v.Commit != nil {
v6 = v.Commit.Sha
v7 = v.Commit.Ref
v8 = v.Commit.Branch
v9 = v.Commit.Message
v10 = v.Commit.Timestamp
v11 = v.Commit.Remote
if v.Commit.Author != nil {
v12 = v.Commit.Author.Login
v13 = v.Commit.Author.Email
}
}
if v.PullRequest != nil {
v14 = v.PullRequest.Number
v15 = v.PullRequest.Title
if v.PullRequest.Base != nil {
v16 = v.PullRequest.Base.Sha
v17 = v.PullRequest.Base.Ref
v18 = v.PullRequest.Base.Branch
v19 = v.PullRequest.Base.Message
v20 = v.PullRequest.Base.Timestamp
v21 = v.PullRequest.Base.Remote
if v.PullRequest.Base.Author != nil {
v22 = v.PullRequest.Base.Author.Login
v23 = v.PullRequest.Base.Author.Email
}
}
}
_, err := db.Exec(query,
&v1,
@ -92,20 +192,52 @@ func updateJob(db jobDB, query string, v *Job) error {
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
&v19,
&v20,
&v21,
&v22,
&v23,
&v0,
)
return err
}
func scanJob(row *sql.Row) (*Job, error) {
func scanBuild(row *sql.Row) (*Build, error) {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int
var v4 int64
var v5 int64
var v6 int64
var v7 []byte
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 int
var v15 string
var v16 string
var v17 string
var v18 string
var v19 string
var v20 string
var v21 string
var v22 string
var v23 string
err := row.Scan(
&v0,
@ -116,36 +248,89 @@ func scanJob(row *sql.Row) (*Job, error) {
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
&v19,
&v20,
&v21,
&v22,
&v23,
)
if err != nil {
return nil, err
}
v := &Job{}
v := &Build{}
v.ID = v0
v.BuildID = v1
v.RepoID = v1
v.Number = v2
v.Status = v3
v.ExitCode = v4
v.Started = v5
v.Finished = v6
json.Unmarshal(v7, &v.Environment)
v.Started = v4
v.Finished = v5
v.Commit = &Commit{}
v.Commit.Sha = v6
v.Commit.Ref = v7
v.Commit.Branch = v8
v.Commit.Message = v9
v.Commit.Timestamp = v10
v.Commit.Remote = v11
v.Commit.Author = &Author{}
v.Commit.Author.Login = v12
v.Commit.Author.Email = v13
v.PullRequest = &PullRequest{}
v.PullRequest.Number = v14
v.PullRequest.Title = v15
v.PullRequest.Base = &Commit{}
v.PullRequest.Base.Sha = v16
v.PullRequest.Base.Ref = v17
v.PullRequest.Base.Branch = v18
v.PullRequest.Base.Message = v19
v.PullRequest.Base.Timestamp = v20
v.PullRequest.Base.Remote = v21
v.PullRequest.Base.Author = &Author{}
v.PullRequest.Base.Author.Login = v22
v.PullRequest.Base.Author.Email = v23
return v, nil
}
func scanJobs(rows *sql.Rows) ([]*Job, error) {
func scanBuilds(rows *sql.Rows) ([]*Build, error) {
var err error
var vv []*Job
var vv []*Build
for rows.Next() {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int
var v4 int64
var v5 int64
var v6 int64
var v7 []byte
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 int
var v15 string
var v16 string
var v17 string
var v18 string
var v19 string
var v20 string
var v21 string
var v22 string
var v23 string
err = rows.Scan(
&v0,
&v1,
@ -155,146 +340,346 @@ func scanJobs(rows *sql.Rows) ([]*Job, error) {
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
&v19,
&v20,
&v21,
&v22,
&v23,
)
if err != nil {
return vv, err
}
v := &Job{}
v := &Build{}
v.ID = v0
v.BuildID = v1
v.RepoID = v1
v.Number = v2
v.Status = v3
v.ExitCode = v4
v.Started = v5
v.Finished = v6
json.Unmarshal(v7, &v.Environment)
v.Started = v4
v.Finished = v5
v.Commit = &Commit{}
v.Commit.Sha = v6
v.Commit.Ref = v7
v.Commit.Branch = v8
v.Commit.Message = v9
v.Commit.Timestamp = v10
v.Commit.Remote = v11
v.Commit.Author = &Author{}
v.Commit.Author.Login = v12
v.Commit.Author.Email = v13
v.PullRequest = &PullRequest{}
v.PullRequest.Number = v14
v.PullRequest.Title = v15
v.PullRequest.Base = &Commit{}
v.PullRequest.Base.Sha = v16
v.PullRequest.Base.Ref = v17
v.PullRequest.Base.Branch = v18
v.PullRequest.Base.Message = v19
v.PullRequest.Base.Timestamp = v20
v.PullRequest.Base.Remote = v21
v.PullRequest.Base.Author = &Author{}
v.PullRequest.Base.Author.Login = v22
v.PullRequest.Base.Author.Email = v23
vv = append(vv, v)
}
return vv, rows.Err()
}
const stmtJobSelectList = `
const stmtBuildSelectList = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
build_id
,build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
FROM builds
`
const stmtJobSelectRange = `
const stmtBuildSelectRange = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
build_id
,build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
FROM builds
LIMIT ? OFFSET ?
`
const stmtJobSelect = `
const stmtBuildSelect = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
WHERE job_id = ?
build_id
,build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
FROM builds
WHERE build_id = ?
`
const stmtJobSelectJobBuildId = `
const stmtBuildSelectBuildRepoId = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
WHERE job_build_id = ?
build_id
,build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
FROM builds
WHERE build_repo_id = ?
`
const stmtJobSelectBuildNumber = `
const stmtBuildSelectBuildNumber = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
WHERE job_build_id = ?
AND job_number = ?
build_id
,build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
FROM builds
WHERE build_repo_id = ?
AND build_number = ?
`
const stmtJobSelectCount = `
const stmtBuildSelectCommitBranch = `
SELECT
build_id
,build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
FROM builds
WHERE build_branch = ?
AND build_branch = ?
`
const stmtBuildSelectCount = `
SELECT count(1)
FROM jobs
FROM builds
`
const stmtJobInsert = `
INSERT INTO jobs (
job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
) VALUES (?,?,?,?,?,?,?);
const stmtBuildInsert = `
INSERT INTO builds (
build_repo_id
,build_number
,build_status
,build_started
,build_finished
,build_commit_sha
,build_commit_ref
,build_commit_branch
,build_commit_message
,build_commit_timestamp
,build_commit_remote
,build_commit_author_login
,build_commit_author_email
,build_pull_request_number
,build_pull_request_title
,build_pull_request_base_sha
,build_pull_request_base_ref
,build_pull_request_base_branch
,build_pull_request_base_message
,build_pull_request_base_timestamp
,build_pull_request_base_remote
,build_pull_request_base_author_login
,build_pull_request_base_author_email
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);
`
const stmtJobUpdate = `
UPDATE jobs SET
job_build_id = ?
,job_number = ?
,job_status = ?
,job_exit_code = ?
,job_started = ?
,job_finished = ?
,job_environment = ?
WHERE job_id = ?
const stmtBuildUpdate = `
UPDATE builds SET
build_repo_id = ?
,build_number = ?
,build_status = ?
,build_started = ?
,build_finished = ?
,build_commit_sha = ?
,build_commit_ref = ?
,build_commit_branch = ?
,build_commit_message = ?
,build_commit_timestamp = ?
,build_commit_remote = ?
,build_commit_author_login = ?
,build_commit_author_email = ?
,build_pull_request_number = ?
,build_pull_request_title = ?
,build_pull_request_base_sha = ?
,build_pull_request_base_ref = ?
,build_pull_request_base_branch = ?
,build_pull_request_base_message = ?
,build_pull_request_base_timestamp = ?
,build_pull_request_base_remote = ?
,build_pull_request_base_author_login = ?
,build_pull_request_base_author_email = ?
WHERE build_id = ?
`
const stmtJobDelete = `
DELETE FROM jobs
WHERE job_id = ?
const stmtBuildDelete = `
DELETE FROM builds
WHERE build_id = ?
`
const stmtJobTable = `
CREATE TABLE IF NOT EXISTS jobs (
job_id INTEGER PRIMARY KEY AUTOINCREMENT
,job_build_id INTEGER
,job_number INTEGER
,job_status VARCHAR
,job_exit_code INTEGER
,job_started INTEGER
,job_finished INTEGER
,job_environmentVARCHAR(2048)
const stmtBuildTable = `
CREATE TABLE IF NOT EXISTS builds (
build_id INTEGER PRIMARY KEY AUTOINCREMENT
,build_repo_id INTEGER
,build_number INTEGER
,build_status VARCHAR(512)
,build_started INTEGER
,build_finished INTEGER
,build_commit_sha VARCHAR(512)
,build_commit_ref VARCHAR(512)
,build_commit_branch VARCHAR(512)
,build_commit_message VARCHAR(512)
,build_commit_timestamp VARCHAR(512)
,build_commit_remote VARCHAR(512)
,build_commit_author_login VARCHAR(512)
,build_commit_author_email VARCHAR(512)
,build_pull_request_number INTEGER
,build_pull_request_title VARCHAR(512)
,build_pull_request_base_sha VARCHAR(512)
,build_pull_request_base_ref VARCHAR(512)
,build_pull_request_base_branch VARCHAR(512)
,build_pull_request_base_message VARCHAR(512)
,build_pull_request_base_timestamp VARCHAR(512)
,build_pull_request_base_remote VARCHAR(512)
,build_pull_request_base_author_login VARCHAR(512)
,build_pull_request_base_author_email VARCHAR(512)
);
`
const stmtJobJobBuildIdIndex = `
CREATE INDEX IF NOT EXISTS ix_job_build_id ON jobs (job_build_id);
const stmtBuildBuildRepoIdIndex = `
CREATE INDEX IF NOT EXISTS ix_build_repo_id ON builds (build_repo_id);
`
const stmtJobBuildNumberIndex = `
CREATE UNIQUE INDEX IF NOT EXISTS ux_build_number ON jobs (job_build_id,job_number);
const stmtBuildBuildNumberIndex = `
CREATE UNIQUE INDEX IF NOT EXISTS ux_build_number ON builds (build_repo_id,build_number);
`
const stmtBuildCommitBranchIndex = `
CREATE INDEX IF NOT EXISTS ix_commit_branch ON builds (build_branch,build_branch);
`

View file

@ -7,119 +7,166 @@ import (
"github.com/drone/drone/pkg/types"
)
func TestBuildstore(t *testing.T) {
func TestCommitstore(t *testing.T) {
db := mustConnectTest()
bs := NewJobstore(db)
cs := NewCommitstore(db)
bs := NewBuildstore(db)
defer db.Close()
g := goblin.Goblin(t)
g.Describe("Jobstore", func() {
g.Describe("Buildstore", func() {
// before each test we purge the package table data from the database.
// before each test be sure to purge the package
// table data from the database.
g.BeforeEach(func() {
db.Exec("DELETE FROM builds")
db.Exec("DELETE FROM jobs")
db.Exec("DELETE FROM commits")
})
g.It("Should Set a job", func() {
job := &types.Job{
BuildID: 1,
Status: "pending",
ExitCode: 0,
Number: 1,
}
err1 := bs.AddJob(job)
g.Assert(err1 == nil).IsTrue()
g.Assert(job.ID != 0).IsTrue()
job.Status = "started"
err2 := bs.SetJob(job)
g.Assert(err2 == nil).IsTrue()
getjob, err3 := bs.Job(job.ID)
g.Assert(err3 == nil).IsTrue()
g.Assert(getjob.Status).Equal(job.Status)
})
g.It("Should Get a Job by ID", func() {
job := &types.Job{
BuildID: 1,
Status: "pending",
ExitCode: 1,
Number: 1,
Environment: map[string]string{"foo": "bar"},
}
err1 := bs.AddJob(job)
g.Assert(err1 == nil).IsTrue()
g.Assert(job.ID != 0).IsTrue()
getjob, err2 := bs.Job(job.ID)
g.Assert(err2 == nil).IsTrue()
g.Assert(getjob.ID).Equal(job.ID)
g.Assert(getjob.Status).Equal(job.Status)
g.Assert(getjob.ExitCode).Equal(job.ExitCode)
g.Assert(getjob.Environment).Equal(job.Environment)
g.Assert(getjob.Environment["foo"]).Equal("bar")
})
g.It("Should Get a Job by Number", func() {
job := &types.Job{
BuildID: 1,
Status: "pending",
ExitCode: 1,
Number: 1,
}
err1 := bs.AddJob(job)
g.Assert(err1 == nil).IsTrue()
g.Assert(job.ID != 0).IsTrue()
getjob, err2 := bs.JobNumber(&types.Commit{ID: 1}, 1)
g.Assert(err2 == nil).IsTrue()
g.Assert(getjob.ID).Equal(job.ID)
g.Assert(getjob.Status).Equal(job.Status)
})
g.It("Should Get a List of Jobs by Commit", func() {
//In order for buid to be populated,
//The AddCommit command will insert builds
//if the Commit.Builds array is populated
//Add Commit.
commit := types.Commit{
g.It("Should Post a Build", func() {
build := types.Build{
RepoID: 1,
State: types.StateSuccess,
Ref: "refs/heads/master",
Sha: "14710626f22791619d3b7e9ccf58b10374e5b76d",
Builds: []*types.Job{
&types.Job{
BuildID: 1,
Status: "success",
ExitCode: 0,
Number: 1,
},
&types.Job{
BuildID: 3,
Status: "error",
ExitCode: 1,
Number: 2,
},
&types.Job{
BuildID: 5,
Status: "pending",
ExitCode: 0,
Number: 3,
},
Status: types.StateSuccess,
Commit: &types.Commit{
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
},
}
//
err1 := cs.AddCommit(&commit)
g.Assert(err1 == nil).IsTrue()
getjobs, err2 := bs.JobList(&commit)
g.Assert(err2 == nil).IsTrue()
g.Assert(len(getjobs)).Equal(3)
g.Assert(getjobs[0].Number).Equal(1)
g.Assert(getjobs[0].Status).Equal(types.StateSuccess)
err := bs.AddBuild(&build)
g.Assert(err == nil).IsTrue()
g.Assert(build.ID != 0).IsTrue()
g.Assert(build.Number).Equal(1)
g.Assert(build.Commit.Ref).Equal("refs/heads/master")
g.Assert(build.Commit.Sha).Equal("85f8c029b902ed9400bc600bac301a0aadb144ac")
})
g.It("Should Put a Build", func() {
build := types.Build{
RepoID: 1,
Number: 5,
Status: types.StatePending,
Commit: &types.Commit{
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
},
}
bs.AddBuild(&build)
build.Status = types.StateRunning
err1 := bs.SetBuild(&build)
getbuild, err2 := bs.Build(build.ID)
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(build.ID).Equal(getbuild.ID)
g.Assert(build.RepoID).Equal(getbuild.RepoID)
g.Assert(build.Status).Equal(getbuild.Status)
g.Assert(build.Number).Equal(getbuild.Number)
})
g.It("Should Get a Build", func() {
build := types.Build{
RepoID: 1,
Status: types.StateSuccess,
}
bs.AddBuild(&build)
getbuild, err := bs.Build(build.ID)
g.Assert(err == nil).IsTrue()
g.Assert(build.ID).Equal(getbuild.ID)
g.Assert(build.RepoID).Equal(getbuild.RepoID)
g.Assert(build.Status).Equal(getbuild.Status)
})
g.It("Should Get a Build by Number", func() {
build1 := &types.Build{
RepoID: 1,
Status: types.StatePending,
}
build2 := &types.Build{
RepoID: 1,
Status: types.StatePending,
}
err1 := bs.AddBuild(build1)
err2 := bs.AddBuild(build2)
getbuild, err3 := bs.BuildNumber(&types.Repo{ID: 1}, build2.Number)
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(err3 == nil).IsTrue()
g.Assert(build2.ID).Equal(getbuild.ID)
g.Assert(build2.RepoID).Equal(getbuild.RepoID)
g.Assert(build2.Number).Equal(getbuild.Number)
})
g.It("Should Kill Pending or Started Builds", func() {
build1 := &types.Build{
RepoID: 1,
Status: types.StateRunning,
}
build2 := &types.Build{
RepoID: 1,
Status: types.StatePending,
}
bs.AddBuild(build1)
bs.AddBuild(build2)
err1 := bs.KillBuilds()
getbuild1, err2 := bs.Build(build1.ID)
getbuild2, err3 := bs.Build(build2.ID)
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(err3 == nil).IsTrue()
g.Assert(getbuild1.Status).Equal(types.StateKilled)
g.Assert(getbuild2.Status).Equal(types.StateKilled)
})
g.It("Should get recent Builds", func() {
build1 := &types.Build{
RepoID: 1,
Status: types.StateFailure,
}
build2 := &types.Build{
RepoID: 1,
Status: types.StateSuccess,
}
bs.AddBuild(build1)
bs.AddBuild(build2)
builds, err := bs.BuildList(&types.Repo{ID: 1}, 20, 0)
g.Assert(err == nil).IsTrue()
g.Assert(len(builds)).Equal(2)
g.Assert(builds[0].ID).Equal(build2.ID)
g.Assert(builds[0].RepoID).Equal(build2.RepoID)
g.Assert(builds[0].Status).Equal(build2.Status)
})
//
// g.It("Should get the last Commit", func() {
// commit1 := &types.Commit{
// RepoID: 1,
// State: types.StateFailure,
// Branch: "master",
// Ref: "refs/heads/master",
// Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
// }
// commit2 := &types.Commit{
// RepoID: 1,
// State: types.StateFailure,
// Branch: "master",
// Ref: "refs/heads/master",
// Sha: "8d6a233744a5dcacbf2605d4592a4bfe8b37320d",
// }
// commit3 := &types.Commit{
// RepoID: 1,
// State: types.StateSuccess,
// Branch: "dev",
// Ref: "refs/heads/dev",
// Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
// }
// err1 := bs.AddCommit(commit1)
// err2 := bs.AddCommit(commit2)
// err3 := bs.AddCommit(commit3)
// last, err4 := bs.CommitLast(&types.Repo{ID: 1}, "master")
// g.Assert(err1 == nil).IsTrue()
// g.Assert(err2 == nil).IsTrue()
// g.Assert(err3 == nil).IsTrue()
// g.Assert(err4 == nil).IsTrue()
// g.Assert(last.ID).Equal(commit2.ID)
// g.Assert(last.RepoID).Equal(commit2.RepoID)
// g.Assert(last.Sequence).Equal(commit2.Sequence)
// })
})
}

View file

@ -1,148 +0,0 @@
package builtin
import (
"database/sql"
"time"
"github.com/drone/drone/pkg/types"
)
type Commitstore struct {
*sql.DB
}
func NewCommitstore(db *sql.DB) *Commitstore {
return &Commitstore{db}
}
// Commit gets a commit by ID
func (db *Commitstore) Commit(id int64) (*types.Commit, error) {
return getCommit(db, rebind(stmtCommitSelect), id)
}
// CommitSeq gets the specified commit sequence for the
// named repository and commit number
func (db *Commitstore) CommitSeq(repo *types.Repo, seq int) (*types.Commit, error) {
return getCommit(db, rebind(stmtCommitSelectCommitSeq), repo.ID, seq)
}
// CommitLast gets the last executed commit for the
// named repository.
func (db *Commitstore) CommitLast(repo *types.Repo, branch string) (*types.Commit, error) {
return getCommit(db, rebind(commitLastQuery), repo.ID, branch)
}
// CommitList gets a list of recent commits for the
// named repository.
func (db *Commitstore) CommitList(repo *types.Repo, limit, offset int) ([]*types.Commit, error) {
return getCommits(db, rebind(commitListQuery), repo.ID, limit, offset)
}
// AddCommit inserts a new commit in the datastore.
func (db *Commitstore) AddCommit(commit *types.Commit) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
// extract the next commit number from the database
row := tx.QueryRow(rebind(commitNumberLast), commit.RepoID)
if row != nil {
row.Scan(&commit.Sequence)
}
commit.Sequence = commit.Sequence + 1 // increment
commit.Created = time.Now().UTC().Unix()
commit.Updated = time.Now().UTC().Unix()
err = createCommit(tx, rebind(stmtCommitInsert), commit)
if err != nil {
return err
}
for _, job := range commit.Builds {
job.BuildID = commit.ID
err := createJob(tx, rebind(stmtJobInsert), job)
if err != nil {
return err
}
}
return tx.Commit()
}
// SetCommit updates an existing commit and commit tasks.
func (db *Commitstore) SetCommit(commit *types.Commit) error {
tx, err := db.Begin()
if err != nil {
return err
}
defer tx.Rollback()
commit.Updated = time.Now().UTC().Unix()
err = updateCommit(tx, rebind(stmtCommitUpdate), commit)
if err != nil {
return err
}
for _, job := range commit.Builds {
err = updateJob(tx, rebind(stmtJobUpdate), job)
if err != nil {
return err
}
}
return tx.Commit()
}
// KillCommits updates all pending or started commits
// in the datastore settings the status to killed.
func (db *Commitstore) KillCommits() error {
var _, err1 = db.Exec(rebind(buildKillStmt))
if err1 != nil {
return err1
}
var _, err2 = db.Exec(rebind(commitKillStmt))
return err2
}
// Commit table name in database.
const commitTable = "commits"
// SQL query to retrieve the latest commits across all branches.
const commitListQuery = `
SELECT *
FROM commits
WHERE commit_repo_id = ?
ORDER BY commit_sequence DESC
LIMIT ? OFFSET ?
`
// SQL query to retrieve the most recent commit.
// TODO exclude pull requests
const commitLastQuery = `
SELECT *
FROM commits
WHERE commit_repo_id = ?
AND commit_branch = ?
ORDER BY commit_sequence DESC
LIMIT 1
`
// SQL statement to cancel all running commits.
const commitKillStmt = `
UPDATE commits SET commit_state = 'killed'
WHERE commit_state IN ('pending', 'running');
`
// SQL statement to cancel all running commits.
const buildKillStmt = `
UPDATE jobs SET job_status = 'killed'
WHERE job_status IN ('pending', 'running');
`
// SQL statement to retrieve the commit number for
// a commit
const commitNumberLast = `
SELECT MAX(commit_sequence)
FROM commits
WHERE commit_repo_id = ?
`

View file

@ -1,520 +0,0 @@
package builtin
// DO NOT EDIT
// code generated by go:generate
import (
"database/sql"
"encoding/json"
. "github.com/drone/drone/pkg/types"
)
var _ = json.Marshal
// generic database interface, matching both *sql.Db and *sql.Tx
type commitDB interface {
Exec(query string, args ...interface{}) (sql.Result, error)
Query(query string, args ...interface{}) (*sql.Rows, error)
QueryRow(query string, args ...interface{}) *sql.Row
}
func getCommit(db commitDB, query string, args ...interface{}) (*Commit, error) {
row := db.QueryRow(query, args...)
return scanCommit(row)
}
func getCommits(db commitDB, query string, args ...interface{}) ([]*Commit, error) {
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
return scanCommits(rows)
}
func createCommit(db commitDB, query string, v *Commit) error {
var v0 int64
var v1 int
var v2 string
var v3 int64
var v4 int64
var v5 string
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 string
var v15 string
var v16 int64
var v17 int64
v0 = v.RepoID
v1 = v.Sequence
v2 = v.State
v3 = v.Started
v4 = v.Finished
v5 = v.Sha
v6 = v.Ref
v7 = v.PullRequest
v8 = v.Branch
v9 = v.Author
v10 = v.Gravatar
v11 = v.Timestamp
v12 = v.Message
v13 = v.SourceRemote
v14 = v.SourceBranch
v15 = v.SourceSha
v16 = v.Created
v17 = v.Updated
res, err := db.Exec(query,
&v0,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
)
if err != nil {
return err
}
v.ID, err = res.LastInsertId()
return err
}
func updateCommit(db commitDB, query string, v *Commit) error {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int64
var v5 int64
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 string
var v15 string
var v16 string
var v17 int64
var v18 int64
v0 = v.ID
v1 = v.RepoID
v2 = v.Sequence
v3 = v.State
v4 = v.Started
v5 = v.Finished
v6 = v.Sha
v7 = v.Ref
v8 = v.PullRequest
v9 = v.Branch
v10 = v.Author
v11 = v.Gravatar
v12 = v.Timestamp
v13 = v.Message
v14 = v.SourceRemote
v15 = v.SourceBranch
v16 = v.SourceSha
v17 = v.Created
v18 = v.Updated
_, err := db.Exec(query,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
&v0,
)
return err
}
func scanCommit(row *sql.Row) (*Commit, error) {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int64
var v5 int64
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 string
var v15 string
var v16 string
var v17 int64
var v18 int64
err := row.Scan(
&v0,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
)
if err != nil {
return nil, err
}
v := &Commit{}
v.ID = v0
v.RepoID = v1
v.Sequence = v2
v.State = v3
v.Started = v4
v.Finished = v5
v.Sha = v6
v.Ref = v7
v.PullRequest = v8
v.Branch = v9
v.Author = v10
v.Gravatar = v11
v.Timestamp = v12
v.Message = v13
v.SourceRemote = v14
v.SourceBranch = v15
v.SourceSha = v16
v.Created = v17
v.Updated = v18
return v, nil
}
func scanCommits(rows *sql.Rows) ([]*Commit, error) {
var err error
var vv []*Commit
for rows.Next() {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int64
var v5 int64
var v6 string
var v7 string
var v8 string
var v9 string
var v10 string
var v11 string
var v12 string
var v13 string
var v14 string
var v15 string
var v16 string
var v17 int64
var v18 int64
err = rows.Scan(
&v0,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
&v8,
&v9,
&v10,
&v11,
&v12,
&v13,
&v14,
&v15,
&v16,
&v17,
&v18,
)
if err != nil {
return vv, err
}
v := &Commit{}
v.ID = v0
v.RepoID = v1
v.Sequence = v2
v.State = v3
v.Started = v4
v.Finished = v5
v.Sha = v6
v.Ref = v7
v.PullRequest = v8
v.Branch = v9
v.Author = v10
v.Gravatar = v11
v.Timestamp = v12
v.Message = v13
v.SourceRemote = v14
v.SourceBranch = v15
v.SourceSha = v16
v.Created = v17
v.Updated = v18
vv = append(vv, v)
}
return vv, rows.Err()
}
const stmtCommitSelectList = `
SELECT
commit_id
,commit_repo_id
,commit_sequence
,commit_state
,commit_started
,commit_finished
,commit_sha
,commit_ref
,commit_pull_request
,commit_branch
,commit_author
,commit_gravatar
,commit_timestamp
,commit_message
,commit_source_remote
,commit_source_branch
,commit_source_sha
,commit_created
,commit_updated
FROM commits
`
const stmtCommitSelectRange = `
SELECT
commit_id
,commit_repo_id
,commit_sequence
,commit_state
,commit_started
,commit_finished
,commit_sha
,commit_ref
,commit_pull_request
,commit_branch
,commit_author
,commit_gravatar
,commit_timestamp
,commit_message
,commit_source_remote
,commit_source_branch
,commit_source_sha
,commit_created
,commit_updated
FROM commits
LIMIT ? OFFSET ?
`
const stmtCommitSelect = `
SELECT
commit_id
,commit_repo_id
,commit_sequence
,commit_state
,commit_started
,commit_finished
,commit_sha
,commit_ref
,commit_pull_request
,commit_branch
,commit_author
,commit_gravatar
,commit_timestamp
,commit_message
,commit_source_remote
,commit_source_branch
,commit_source_sha
,commit_created
,commit_updated
FROM commits
WHERE commit_id = ?
`
const stmtCommitSelectCommitSeq = `
SELECT
commit_id
,commit_repo_id
,commit_sequence
,commit_state
,commit_started
,commit_finished
,commit_sha
,commit_ref
,commit_pull_request
,commit_branch
,commit_author
,commit_gravatar
,commit_timestamp
,commit_message
,commit_source_remote
,commit_source_branch
,commit_source_sha
,commit_created
,commit_updated
FROM commits
WHERE commit_repo_id = ?
AND commit_sequence = ?
`
const stmtCommitSelectCommitRepoId = `
SELECT
commit_id
,commit_repo_id
,commit_sequence
,commit_state
,commit_started
,commit_finished
,commit_sha
,commit_ref
,commit_pull_request
,commit_branch
,commit_author
,commit_gravatar
,commit_timestamp
,commit_message
,commit_source_remote
,commit_source_branch
,commit_source_sha
,commit_created
,commit_updated
FROM commits
WHERE commit_repo_id = ?
`
const stmtCommitSelectCount = `
SELECT count(1)
FROM commits
`
const stmtCommitInsert = `
INSERT INTO commits (
commit_repo_id
,commit_sequence
,commit_state
,commit_started
,commit_finished
,commit_sha
,commit_ref
,commit_pull_request
,commit_branch
,commit_author
,commit_gravatar
,commit_timestamp
,commit_message
,commit_source_remote
,commit_source_branch
,commit_source_sha
,commit_created
,commit_updated
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?);
`
const stmtCommitUpdate = `
UPDATE commits SET
commit_repo_id = ?
,commit_sequence = ?
,commit_state = ?
,commit_started = ?
,commit_finished = ?
,commit_sha = ?
,commit_ref = ?
,commit_pull_request = ?
,commit_branch = ?
,commit_author = ?
,commit_gravatar = ?
,commit_timestamp = ?
,commit_message = ?
,commit_source_remote = ?
,commit_source_branch = ?
,commit_source_sha = ?
,commit_created = ?
,commit_updated = ?
WHERE commit_id = ?
`
const stmtCommitDelete = `
DELETE FROM commits
WHERE commit_id = ?
`
const stmtCommitTable = `
CREATE TABLE IF NOT EXISTS commits (
commit_id INTEGER PRIMARY KEY AUTOINCREMENT
,commit_repo_id INTEGER
,commit_sequence INTEGER
,commit_state VARCHAR
,commit_started INTEGER
,commit_finished INTEGER
,commit_sha VARCHAR
,commit_ref VARCHAR
,commit_pull_request VARCHAR
,commit_branch VARCHAR
,commit_author VARCHAR
,commit_gravatar VARCHAR
,commit_timestamp VARCHAR
,commit_message VARCHAR
,commit_source_remote VARCHAR
,commit_source_branch VARCHAR
,commit_source_sha VARCHAR
,commit_created INTEGER
,commit_updated INTEGER
);
`
const stmtCommitCommitSeqIndex = `
CREATE UNIQUE INDEX IF NOT EXISTS ux_commit_seq ON commits (commit_repo_id,commit_sequence);
`
const stmtCommitCommitRepoIdIndex = `
CREATE INDEX IF NOT EXISTS ix_commit_repo_id ON commits (commit_repo_id);
`

View file

@ -1,178 +0,0 @@
package builtin
import (
"testing"
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
"github.com/drone/drone/pkg/types"
)
func TestCommitstore(t *testing.T) {
db := mustConnectTest()
bs := NewCommitstore(db)
defer db.Close()
g := goblin.Goblin(t)
g.Describe("Commitstore", func() {
// before each test be sure to purge the package
// table data from the database.
g.BeforeEach(func() {
db.Exec("DELETE FROM commits")
db.Exec("DELETE FROM tasks")
})
g.It("Should Post a Commit", func() {
commit := types.Commit{
RepoID: 1,
State: types.StateSuccess,
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
err := bs.AddCommit(&commit)
g.Assert(err == nil).IsTrue()
g.Assert(commit.ID != 0).IsTrue()
g.Assert(commit.Sequence).Equal(1)
})
g.It("Should Put a Commit", func() {
commit := types.Commit{
RepoID: 1,
Sequence: 5,
State: types.StatePending,
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
bs.AddCommit(&commit)
commit.State = types.StateRunning
err1 := bs.SetCommit(&commit)
getcommit, err2 := bs.Commit(commit.ID)
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(commit.ID).Equal(getcommit.ID)
g.Assert(commit.RepoID).Equal(getcommit.RepoID)
g.Assert(commit.State).Equal(getcommit.State)
g.Assert(commit.Sequence).Equal(getcommit.Sequence)
})
g.It("Should Get a Commit", func() {
commit := types.Commit{
RepoID: 1,
State: types.StateSuccess,
}
bs.AddCommit(&commit)
getcommit, err := bs.Commit(commit.ID)
g.Assert(err == nil).IsTrue()
g.Assert(commit.ID).Equal(getcommit.ID)
g.Assert(commit.RepoID).Equal(getcommit.RepoID)
g.Assert(commit.State).Equal(getcommit.State)
})
g.It("Should Get a Commit by Sequence", func() {
commit1 := &types.Commit{
RepoID: 1,
State: types.StatePending,
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
commit2 := &types.Commit{
RepoID: 1,
State: types.StatePending,
Ref: "refs/heads/dev",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
err1 := bs.AddCommit(commit1)
err2 := bs.AddCommit(commit2)
getcommit, err3 := bs.CommitSeq(&types.Repo{ID: 1}, commit2.Sequence)
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(err3 == nil).IsTrue()
g.Assert(commit2.ID).Equal(getcommit.ID)
g.Assert(commit2.RepoID).Equal(getcommit.RepoID)
g.Assert(commit2.Sequence).Equal(getcommit.Sequence)
})
g.It("Should Kill Pending or Started Commits", func() {
commit1 := &types.Commit{
RepoID: 1,
State: types.StateRunning,
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
commit2 := &types.Commit{
RepoID: 1,
State: types.StatePending,
Ref: "refs/heads/dev",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
bs.AddCommit(commit1)
bs.AddCommit(commit2)
err1 := bs.KillCommits()
getcommit1, err2 := bs.Commit(commit1.ID)
getcommit2, err3 := bs.Commit(commit2.ID)
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(err3 == nil).IsTrue()
g.Assert(getcommit1.State).Equal(types.StateKilled)
g.Assert(getcommit2.State).Equal(types.StateKilled)
})
g.It("Should get recent Commits", func() {
commit1 := &types.Commit{
RepoID: 1,
State: types.StateFailure,
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
commit2 := &types.Commit{
RepoID: 1,
State: types.StateSuccess,
Ref: "refs/heads/dev",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
bs.AddCommit(commit1)
bs.AddCommit(commit2)
commits, err := bs.CommitList(&types.Repo{ID: 1}, 20, 0)
g.Assert(err == nil).IsTrue()
g.Assert(len(commits)).Equal(2)
g.Assert(commits[0].ID).Equal(commit2.ID)
g.Assert(commits[0].RepoID).Equal(commit2.RepoID)
g.Assert(commits[0].State).Equal(commit2.State)
})
g.It("Should get the last Commit", func() {
commit1 := &types.Commit{
RepoID: 1,
State: types.StateFailure,
Branch: "master",
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
commit2 := &types.Commit{
RepoID: 1,
State: types.StateFailure,
Branch: "master",
Ref: "refs/heads/master",
Sha: "8d6a233744a5dcacbf2605d4592a4bfe8b37320d",
}
commit3 := &types.Commit{
RepoID: 1,
State: types.StateSuccess,
Branch: "dev",
Ref: "refs/heads/dev",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
}
err1 := bs.AddCommit(commit1)
err2 := bs.AddCommit(commit2)
err3 := bs.AddCommit(commit3)
last, err4 := bs.CommitLast(&types.Repo{ID: 1}, "master")
g.Assert(err1 == nil).IsTrue()
g.Assert(err2 == nil).IsTrue()
g.Assert(err3 == nil).IsTrue()
g.Assert(err4 == nil).IsTrue()
g.Assert(last.ID).Equal(commit2.ID)
g.Assert(last.RepoID).Equal(commit2.RepoID)
g.Assert(last.Sequence).Equal(commit2.Sequence)
})
})
}

40
pkg/store/builtin/job.go Normal file
View file

@ -0,0 +1,40 @@
package builtin
import (
"database/sql"
"github.com/drone/drone/pkg/types"
)
type Jobstore struct {
*sql.DB
}
func NewJobstore(db *sql.DB) *Jobstore {
return &Jobstore{db}
}
// Job returns a Job by ID.
func (db *Jobstore) Job(id int64) (*types.Job, error) {
return getJob(db, rebind(stmtJobSelect), id)
}
// JobNumber returns a job by sequence number.
func (db *Jobstore) JobNumber(build *types.Build, seq int) (*types.Job, error) {
return getJob(db, rebind(stmtJobSelectBuildNumber), build.ID, seq)
}
// JobList returns a list of all build jobs
func (db *Jobstore) JobList(build *types.Build) ([]*types.Job, error) {
return getJobs(db, rebind(stmtJobSelectJobBuildId), build.ID)
}
// SetJob updates an existing build job.
func (db *Jobstore) SetJob(job *types.Job) error {
return updateJob(db, rebind(stmtJobUpdate), job)
}
// AddJob inserts a build job.
func (db *Jobstore) AddJob(job *types.Job) error {
return createJob(db, rebind(stmtJobInsert), job)
}

View file

@ -0,0 +1,300 @@
package builtin
// DO NOT EDIT
// code generated by go:generate
import (
"database/sql"
"encoding/json"
. "github.com/drone/drone/pkg/types"
)
var _ = json.Marshal
// generic database interface, matching both *sql.Db and *sql.Tx
type jobDB interface {
Exec(query string, args ...interface{}) (sql.Result, error)
Query(query string, args ...interface{}) (*sql.Rows, error)
QueryRow(query string, args ...interface{}) *sql.Row
}
func getJob(db jobDB, query string, args ...interface{}) (*Job, error) {
row := db.QueryRow(query, args...)
return scanJob(row)
}
func getJobs(db jobDB, query string, args ...interface{}) ([]*Job, error) {
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
return scanJobs(rows)
}
func createJob(db jobDB, query string, v *Job) error {
var v0 int64
var v1 int
var v2 string
var v3 int
var v4 int64
var v5 int64
var v6 []byte
v0 = v.BuildID
v1 = v.Number
v2 = v.Status
v3 = v.ExitCode
v4 = v.Started
v5 = v.Finished
v6, _ = json.Marshal(v.Environment)
res, err := db.Exec(query,
&v0,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
)
if err != nil {
return err
}
v.ID, err = res.LastInsertId()
return err
}
func updateJob(db jobDB, query string, v *Job) error {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int
var v5 int64
var v6 int64
var v7 []byte
v0 = v.ID
v1 = v.BuildID
v2 = v.Number
v3 = v.Status
v4 = v.ExitCode
v5 = v.Started
v6 = v.Finished
v7, _ = json.Marshal(v.Environment)
_, err := db.Exec(query,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
&v0,
)
return err
}
func scanJob(row *sql.Row) (*Job, error) {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int
var v5 int64
var v6 int64
var v7 []byte
err := row.Scan(
&v0,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
)
if err != nil {
return nil, err
}
v := &Job{}
v.ID = v0
v.BuildID = v1
v.Number = v2
v.Status = v3
v.ExitCode = v4
v.Started = v5
v.Finished = v6
json.Unmarshal(v7, &v.Environment)
return v, nil
}
func scanJobs(rows *sql.Rows) ([]*Job, error) {
var err error
var vv []*Job
for rows.Next() {
var v0 int64
var v1 int64
var v2 int
var v3 string
var v4 int
var v5 int64
var v6 int64
var v7 []byte
err = rows.Scan(
&v0,
&v1,
&v2,
&v3,
&v4,
&v5,
&v6,
&v7,
)
if err != nil {
return vv, err
}
v := &Job{}
v.ID = v0
v.BuildID = v1
v.Number = v2
v.Status = v3
v.ExitCode = v4
v.Started = v5
v.Finished = v6
json.Unmarshal(v7, &v.Environment)
vv = append(vv, v)
}
return vv, rows.Err()
}
const stmtJobSelectList = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
`
const stmtJobSelectRange = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
LIMIT ? OFFSET ?
`
const stmtJobSelect = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
WHERE job_id = ?
`
const stmtJobSelectJobBuildId = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
WHERE job_build_id = ?
`
const stmtJobSelectBuildNumber = `
SELECT
job_id
,job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
FROM jobs
WHERE job_build_id = ?
AND job_number = ?
`
const stmtJobSelectCount = `
SELECT count(1)
FROM jobs
`
const stmtJobInsert = `
INSERT INTO jobs (
job_build_id
,job_number
,job_status
,job_exit_code
,job_started
,job_finished
,job_environment
) VALUES (?,?,?,?,?,?,?);
`
const stmtJobUpdate = `
UPDATE jobs SET
job_build_id = ?
,job_number = ?
,job_status = ?
,job_exit_code = ?
,job_started = ?
,job_finished = ?
,job_environment = ?
WHERE job_id = ?
`
const stmtJobDelete = `
DELETE FROM jobs
WHERE job_id = ?
`
const stmtJobTable = `
CREATE TABLE IF NOT EXISTS jobs (
job_id INTEGER PRIMARY KEY AUTOINCREMENT
,job_build_id INTEGER
,job_number INTEGER
,job_status VARCHAR(512)
,job_exit_code INTEGER
,job_started INTEGER
,job_finished INTEGER
,job_environmentVARCHAR(2048)
);
`
const stmtJobJobBuildIdIndex = `
CREATE INDEX IF NOT EXISTS ix_job_build_id ON jobs (job_build_id);
`
const stmtJobBuildNumberIndex = `
CREATE UNIQUE INDEX IF NOT EXISTS ux_build_number ON jobs (job_build_id,job_number);
`

View file

@ -0,0 +1,119 @@
package builtin
import (
"testing"
"github.com/drone/drone/Godeps/_workspace/src/github.com/franela/goblin"
"github.com/drone/drone/pkg/types"
)
func TestBuildstore(t *testing.T) {
db := mustConnectTest()
bs := NewJobstore(db)
cs := NewBuildstore(db)
defer db.Close()
g := goblin.Goblin(t)
g.Describe("Jobstore", func() {
// before each test we purge the package table data from the database.
g.BeforeEach(func() {
db.Exec("DELETE FROM jobs")
db.Exec("DELETE FROM builds")
})
g.It("Should Set a job", func() {
job := &types.Job{
BuildID: 1,
Status: "pending",
ExitCode: 0,
Number: 1,
}
err1 := bs.AddJob(job)
g.Assert(err1 == nil).IsTrue()
g.Assert(job.ID != 0).IsTrue()
job.Status = "started"
err2 := bs.SetJob(job)
g.Assert(err2 == nil).IsTrue()
getjob, err3 := bs.Job(job.ID)
g.Assert(err3 == nil).IsTrue()
g.Assert(getjob.Status).Equal(job.Status)
})
g.It("Should Get a Job by ID", func() {
job := &types.Job{
BuildID: 1,
Status: "pending",
ExitCode: 1,
Number: 1,
Environment: map[string]string{"foo": "bar"},
}
err1 := bs.AddJob(job)
g.Assert(err1 == nil).IsTrue()
g.Assert(job.ID != 0).IsTrue()
getjob, err2 := bs.Job(job.ID)
g.Assert(err2 == nil).IsTrue()
g.Assert(getjob.ID).Equal(job.ID)
g.Assert(getjob.Status).Equal(job.Status)
g.Assert(getjob.ExitCode).Equal(job.ExitCode)
g.Assert(getjob.Environment).Equal(job.Environment)
g.Assert(getjob.Environment["foo"]).Equal("bar")
})
g.It("Should Get a Job by Number", func() {
job := &types.Job{
BuildID: 1,
Status: "pending",
ExitCode: 1,
Number: 1,
}
err1 := bs.AddJob(job)
g.Assert(err1 == nil).IsTrue()
g.Assert(job.ID != 0).IsTrue()
getjob, err2 := bs.JobNumber(&types.Build{ID: 1}, 1)
g.Assert(err2 == nil).IsTrue()
g.Assert(getjob.ID).Equal(job.ID)
g.Assert(getjob.Status).Equal(job.Status)
})
g.It("Should Get a List of Jobs by Commit", func() {
build := types.Build{
RepoID: 1,
Status: types.StateSuccess,
Jobs: []*types.Job{
&types.Job{
BuildID: 1,
Status: "success",
ExitCode: 0,
Number: 1,
},
&types.Job{
BuildID: 3,
Status: "error",
ExitCode: 1,
Number: 2,
},
&types.Job{
BuildID: 5,
Status: "pending",
ExitCode: 0,
Number: 3,
},
},
}
//
err1 := cs.AddBuild(&build)
g.Assert(err1 == nil).IsTrue()
getjobs, err2 := bs.JobList(&build)
g.Assert(err2 == nil).IsTrue()
g.Assert(len(getjobs)).Equal(3)
g.Assert(getjobs[0].Number).Equal(1)
g.Assert(getjobs[0].Status).Equal(types.StateSuccess)
})
})
}

View file

@ -12,11 +12,12 @@ func Setup(tx migration.LimitedTx) error {
starTable,
repoTable,
repoUserIndex,
commitTable,
commitRepoIndex,
tokenTable,
buildTable,
buildCommitIndex,
buildRepoIndex,
buildBranchIndex,
tokenTable,
jobTable,
jobBuildIndex,
statusTable,
statusCommitIndex,
blobTable,
@ -84,33 +85,42 @@ CREATE TABLE IF NOT EXISTS stars (
);
`
var commitTable = `
CREATE TABLE IF NOT EXISTS commits (
commit_id INTEGER PRIMARY KEY AUTOINCREMENT
,commit_repo_id INTEGER
,commit_sequence INTEGER
,commit_state VARCHAR(255)
,commit_started INTEGER
,commit_finished INTEGER
,commit_sha VARCHAR(255)
,commit_ref VARCHAR(255)
,commit_branch VARCHAR(255)
,commit_pull_request VARCHAR(255)
,commit_author VARCHAR(255)
,commit_gravatar VARCHAR(255)
,commit_timestamp VARCHAR(255)
,commit_message VARCHAR(1000)
,commit_source_remote VARCHAR(255)
,commit_source_branch VARCHAR(255)
,commit_source_sha VARCHAR(255)
,commit_created INTEGER
,commit_updated INTEGER
,UNIQUE(commit_repo_id, commit_sequence)
var buildTable = `
CREATE TABLE IF NOT EXISTS builds (
build_id INTEGER PRIMARY KEY AUTOINCREMENT
,build_repo_id INTEGER
,build_number INTEGER
,build_status VARCHAR(512)
,build_started INTEGER
,build_finished INTEGER
,build_commit_sha VARCHAR(512)
,build_commit_ref VARCHAR(512)
,build_commit_branch VARCHAR(512)
,build_commit_message VARCHAR(512)
,build_commit_timestamp VARCHAR(512)
,build_commit_remote VARCHAR(512)
,build_commit_author_login VARCHAR(512)
,build_commit_author_email VARCHAR(512)
,build_pull_request_number INTEGER
,build_pull_request_title VARCHAR(512)
,build_pull_request_base_sha VARCHAR(512)
,build_pull_request_base_ref VARCHAR(512)
,build_pull_request_base_branch VARCHAR(512)
,build_pull_request_base_message VARCHAR(512)
,build_pull_request_base_timestamp VARCHAR(512)
,build_pull_request_base_remote VARCHAR(512)
,build_pull_request_base_author_login VARCHAR(512)
,build_pull_request_base_author_email VARCHAR(512)
,UNIQUE(build_repo_id, build_number)
);
`
var commitRepoIndex = `
CREATE INDEX commits_repo_idx ON commits (commit_repo_id);
var buildRepoIndex = `
CREATE INDEX build_repo_idx ON builds (build_repo_id);
`
var buildBranchIndex = `
CREATE INDEX build_branch_idx ON builds (build_commit_branch);
`
var tokenTable = `
@ -129,7 +139,7 @@ var tokenUserIndex = `
CREATE INDEX tokens_user_idx ON tokens (token_user_id);
`
var buildTable = `
var jobTable = `
CREATE TABLE IF NOT EXISTS jobs (
job_id INTEGER PRIMARY KEY AUTOINCREMENT
,job_build_id INTEGER
@ -143,7 +153,7 @@ CREATE TABLE IF NOT EXISTS jobs (
);
`
var buildCommitIndex = `
var jobBuildIndex = `
CREATE INDEX ix_job_build_id ON jobs (job_build_id);
`
@ -176,8 +186,8 @@ CREATE TABLE IF NOT EXISTS blobs (
var agentTable = `
CREATE TABLE IF NOT EXISTS agents (
agent_id INTEGER PRIMARY KEY AUTOINCREMENT
,agent_commit_id INTEGER
,agent_build_id INTEGER
,agent_addr VARCHAR(2000)
,UNIQUE(agent_commit_id)
,UNIQUE(agent_build_id)
);
`

View file

@ -98,7 +98,7 @@ func New(db *sql.DB) store.Store {
return struct {
*Userstore
*Repostore
*Commitstore
*Buildstore
*Jobstore
*Blobstore
*Starstore
@ -107,7 +107,7 @@ func New(db *sql.DB) store.Store {
}{
NewUserstore(db),
NewRepostore(db),
NewCommitstore(db),
NewBuildstore(db),
NewJobstore(db),
NewBlobstore(db),
NewStarstore(db),

View file

@ -72,18 +72,18 @@ SELECT
,r.repo_owner
,r.repo_name
,r.repo_full_name
,c.commit_sequence
,c.commit_state
,c.commit_started
,c.commit_finished
,b.build_number
,b.build_status
,b.build_started
,b.build_finished
FROM
commits c
builds b
,repos r
,stars s
WHERE c.commit_repo_id = r.repo_id
WHERE b.build_repo_id = r.repo_id
AND r.repo_id = s.star_repo_id
AND s.star_user_id = ?
ORDER BY c.commit_sequence DESC
ORDER BY b.build_number DESC
LIMIT ? OFFSET ?
`

View file

@ -10,7 +10,7 @@ import (
func TestUserstore(t *testing.T) {
db := mustConnectTest()
us := NewUserstore(db)
cs := NewCommitstore(db)
cs := NewBuildstore(db)
rs := NewRepostore(db)
ss := NewStarstore(db)
defer db.Close()
@ -25,7 +25,7 @@ func TestUserstore(t *testing.T) {
db.Exec("DELETE FROM stars")
db.Exec("DELETE FROM repos")
db.Exec("DELETE FROM builds")
db.Exec("DELETE FROM tasks")
db.Exec("DELETE FROM jobs")
})
g.It("Should Update a User", func() {
@ -181,33 +181,27 @@ func TestUserstore(t *testing.T) {
rs.AddRepo(repo1)
rs.AddRepo(repo2)
ss.AddStar(&types.User{ID: 1}, repo1)
commit1 := &types.Commit{
build1 := &types.Build{
RepoID: 1,
State: types.StateFailure,
Ref: "refs/heads/master",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
Status: types.StateFailure,
}
commit2 := &types.Commit{
build2 := &types.Build{
RepoID: 1,
State: types.StateSuccess,
Ref: "refs/heads/dev",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
Status: types.StateSuccess,
}
commit3 := &types.Commit{
build3 := &types.Build{
RepoID: 2,
State: types.StateSuccess,
Ref: "refs/heads/dev",
Sha: "85f8c029b902ed9400bc600bac301a0aadb144ac",
Status: types.StateSuccess,
}
cs.AddCommit(commit1)
cs.AddCommit(commit2)
cs.AddCommit(commit3)
commits, err := us.UserFeed(&types.User{ID: 1}, 20, 0)
cs.AddBuild(build1)
cs.AddBuild(build2)
cs.AddBuild(build3)
builds, err := us.UserFeed(&types.User{ID: 1}, 20, 0)
g.Assert(err == nil).IsTrue()
g.Assert(len(commits)).Equal(2)
g.Assert(commits[0].State).Equal(commit2.State)
g.Assert(commits[0].Owner).Equal("bradrydzewski")
g.Assert(commits[0].Name).Equal("drone")
g.Assert(len(builds)).Equal(2)
//g.Assert(builds[0].Status).Equal(commit2.Status)
g.Assert(builds[0].Owner).Equal("bradrydzewski")
g.Assert(builds[0].Name).Equal("drone")
})
})
}

View file

@ -127,30 +127,30 @@ type Store interface {
//
// Commit gets a commit by ID
Commit(int64) (*types.Commit, error)
// Build gets a build by ID
Build(int64) (*types.Build, error)
// CommitSeq gets the specified commit sequence for the
// named repository and commit number
CommitSeq(*types.Repo, int) (*types.Commit, error)
// BuildNumber gets the specified build number for the
// named repository and build number
BuildNumber(*types.Repo, int) (*types.Build, error)
// CommitLast gets the last executed commit for the
// BuildLast gets the last executed build for the
// named repository and branch
CommitLast(*types.Repo, string) (*types.Commit, error)
BuildLast(*types.Repo, string) (*types.Build, error)
// CommitList gets a list of recent commits for the
// BuildList gets a list of recent builds for the
// named repository.
CommitList(*types.Repo, int, int) ([]*types.Commit, error)
BuildList(*types.Repo, int, int) ([]*types.Build, error)
// AddCommit inserts a new commit in the datastore.
AddCommit(*types.Commit) error
// AddBuild inserts a new build in the datastore.
AddBuild(*types.Build) error
// SetCommit updates an existing commit and commit tasks.
SetCommit(*types.Commit) error
// SetBuild updates an existing build and build jobs.
SetBuild(*types.Build) error
// KillCommits updates all pending or started commits
// KillBuilds updates all pending or started builds
// in the datastore settings the status to killed.
KillCommits() error
KillBuilds() error
//
@ -158,10 +158,10 @@ type Store interface {
Job(int64) (*types.Job, error)
// JobNumber returns a jobs by sequence number.
JobNumber(*types.Commit, int) (*types.Job, error)
JobNumber(*types.Build, int) (*types.Job, error)
// JobList returns a list of all commit jobs
JobList(*types.Commit) ([]*types.Job, error)
// JobList returns a list of all build jobs
JobList(*types.Build) ([]*types.Job, error)
// SetJob updates an existing job.
SetJob(*types.Job) error
@ -189,8 +189,8 @@ type Store interface {
//
// Agent returns an agent by ID.
Agent(*types.Commit) (string, error)
Agent(*types.Build) (string, error)
// SetAgent updates an agent in the datastore.
SetAgent(*types.Commit, string) error
SetAgent(*types.Build, string) error
}

View file

@ -1,13 +1,45 @@
package types
type Job struct {
ID int64 `json:"id"`
BuildID int64 `json:"-" sql:"unique:ux_build_number,index:ix_job_build_id"`
Number int `json:"number" sql:"unique:ux_build_number"`
const (
StatePending = "pending"
StateRunning = "running"
StateSuccess = "success"
StateFailure = "failure"
StateKilled = "killed"
StateError = "error"
)
type Build struct {
ID int64
RepoID int64 `json:"-" sql:"unique:ux_build_number,index:ix_build_repo_id"`
Number int `json:"number" sql:"unique:ux_build_number"`
Status string `json:"status"`
ExitCode int `json:"exit_code"`
Started int64 `json:"started_at"`
Finished int64 `json:"finished_at"`
Environment map[string]string `json:"environment" sql:"type:varchar,size:2048"`
Commit *Commit `json:"head_commit"`
PullRequest *PullRequest `json:"pull_request"`
Jobs []*Job `json:"jobs,omitempty" sql:"-"`
}
type PullRequest struct {
Number int `json:"number"`
Title string `json:"title"`
Base *Commit `json:"base_commit"`
}
type Commit struct {
Sha string `json:"sha"`
Ref string `json:"ref"`
Branch string `json:"branch" sql:"index:ix_commit_branch"`
Message string `json:"message"`
Timestamp string `json:"timestamp"`
Remote string `json:"remote"`
Author *Author `json:"author"`
}
type Author struct {
Login string `json:"login"`
Email string `json:"email"`
}

View file

@ -1,34 +0,0 @@
package types
const (
StatePending = "pending"
StateRunning = "running"
StateSuccess = "success"
StateFailure = "failure"
StateKilled = "killed"
StateError = "error"
)
type Commit struct {
ID int64 `meddler:"commit_id,pk" json:"id"`
RepoID int64 `meddler:"commit_repo_id" json:"-" sql:"unique:ux_commit_seq,index:ix_commit_repo_id"`
Sequence int `meddler:"commit_sequence" json:"sequence" sql:"unique:ux_commit_seq"`
State string `meddler:"commit_state" json:"state"`
Started int64 `meddler:"commit_started" json:"started_at"`
Finished int64 `meddler:"commit_finished" json:"finished_at"`
Sha string `meddler:"commit_sha" json:"sha"`
Ref string `meddler:"commit_ref" json:"ref"`
PullRequest string `meddler:"commit_pull_request" json:"pull_request,omitempty"`
Branch string `meddler:"commit_branch" json:"branch"`
Author string `meddler:"commit_author" json:"author"`
Gravatar string `meddler:"commit_gravatar" json:"gravatar"`
Timestamp string `meddler:"commit_timestamp" json:"timestamp"`
Message string `meddler:"commit_message" json:"message"`
SourceRemote string `meddler:"commit_source_remote" json:"source_remote,omitempty"`
SourceBranch string `meddler:"commit_source_branch" json:"source_branch,omitempty"`
SourceSha string `meddler:"commit_source_sha" json:"source_sha,omitempty"`
Created int64 `meddler:"commit_created" json:"created_at"`
Updated int64 `meddler:"commit_updated" json:"updated_at"`
Builds []*Job `meddler:"-" json:"builds,omitempty" sql:"-"`
}

View file

@ -1,6 +1,7 @@
package types
type Hook struct {
Repo *Repo
Commit *Commit
Repo *Repo
Commit *Commit
PullRequest *PullRequest
}

13
pkg/types/job.go Normal file
View file

@ -0,0 +1,13 @@
package types
type Job struct {
ID int64 `json:"id"`
BuildID int64 `json:"-" sql:"unique:ux_build_number,index:ix_job_build_id"`
Number int `json:"number" sql:"unique:ux_build_number"`
Status string `json:"status"`
ExitCode int `json:"exit_code"`
Started int64 `json:"started_at"`
Finished int64 `json:"finished_at"`
Environment map[string]string `json:"environment" sql:"type:varchar,size:2048"`
}