e8b993e7da
This allows you to restrict email notifications to only be sent after the build changes from success to failure or failure to success. It errs on the side of sending the notification; if the build is in another state (hung, for instance) or there was no previous build on the branch the email will also be sent. Since the notify plugin shouldn't really have any responsibility for querying the database to find the previous commit's status, we store it on the commit when we save it.
200 lines
5.4 KiB
Go
200 lines
5.4 KiB
Go
package database
|
|
|
|
import (
|
|
"time"
|
|
|
|
"github.com/drone/drone/shared/model"
|
|
"github.com/russross/meddler"
|
|
)
|
|
|
|
type Commitstore struct {
|
|
meddler.DB
|
|
}
|
|
|
|
func NewCommitstore(db meddler.DB) *Commitstore {
|
|
return &Commitstore{db}
|
|
}
|
|
|
|
// GetCommit retrieves a commit from the
|
|
// datastore for the given ID.
|
|
func (db *Commitstore) GetCommit(id int64) (*model.Commit, error) {
|
|
var commit = new(model.Commit)
|
|
var err = meddler.Load(db, commitTable, commit, id)
|
|
return commit, err
|
|
}
|
|
|
|
// GetCommitSha retrieves a commit from the
|
|
// datastore for the specified repo and sha
|
|
func (db *Commitstore) GetCommitSha(repo *model.Repo, branch, sha string) (*model.Commit, error) {
|
|
var commit = new(model.Commit)
|
|
var err = meddler.QueryRow(db, commit, rebind(commitShaQuery), repo.ID, branch, sha)
|
|
return commit, err
|
|
}
|
|
|
|
// GetCommitLast retrieves the latest commit
|
|
// from the datastore for the specified repository
|
|
// and branch.
|
|
func (db *Commitstore) GetCommitLast(repo *model.Repo, branch string) (*model.Commit, error) {
|
|
var commit = new(model.Commit)
|
|
var err = meddler.QueryRow(db, commit, rebind(commitLastQuery), repo.ID, branch)
|
|
return commit, err
|
|
}
|
|
|
|
// GetCommitPrior retrieves the latest commit
|
|
// from the datastore for the specified repository
|
|
// and branch.
|
|
func (db *Commitstore) GetCommitPrior(oldCommit *model.Commit) (*model.Commit, error) {
|
|
var commit = new(model.Commit)
|
|
var err = meddler.QueryRow(db, commit, rebind(commitPriorQuery), oldCommit.RepoID, oldCommit.Branch, oldCommit.Created)
|
|
return commit, err
|
|
}
|
|
|
|
// GetCommitList retrieves a list of latest commits
|
|
// from the datastore for the specified repository.
|
|
func (db *Commitstore) GetCommitList(repo *model.Repo) ([]*model.Commit, error) {
|
|
var commits []*model.Commit
|
|
var err = meddler.QueryAll(db, &commits, rebind(commitListQuery), repo.ID)
|
|
return commits, err
|
|
}
|
|
|
|
// GetCommitListUser retrieves a list of latest commits
|
|
// from the datastore accessible to the specified user.
|
|
func (db *Commitstore) GetCommitListUser(user *model.User) ([]*model.CommitRepo, error) {
|
|
var commits []*model.CommitRepo
|
|
var err = meddler.QueryAll(db, &commits, rebind(commitListUserQuery), user.ID)
|
|
return commits, err
|
|
}
|
|
|
|
// GetCommitListActivity retrieves an ungrouped list of latest commits
|
|
// from the datastore accessible to the specified user.
|
|
func (db *Commitstore) GetCommitListActivity(user *model.User) ([]*model.CommitRepo, error) {
|
|
var commits []*model.CommitRepo
|
|
var err = meddler.QueryAll(db, &commits, rebind(commitListActivityQuery), user.ID)
|
|
return commits, err
|
|
}
|
|
|
|
// PostCommit saves a commit in the datastore.
|
|
func (db *Commitstore) PostCommit(commit *model.Commit) error {
|
|
if commit.Created == 0 {
|
|
commit.Created = time.Now().UTC().Unix()
|
|
}
|
|
commit.Updated = time.Now().UTC().Unix()
|
|
|
|
priorCommit, err := db.GetCommitPrior(commit)
|
|
if err == nil {
|
|
commit.PriorStatus = priorCommit.Status
|
|
}
|
|
|
|
return meddler.Save(db, commitTable, commit)
|
|
}
|
|
|
|
// PutCommit saves a commit in the datastore.
|
|
func (db *Commitstore) PutCommit(commit *model.Commit) error {
|
|
return db.PostCommit(commit)
|
|
}
|
|
|
|
// DelCommit removes the commit from the datastore.
|
|
func (db *Commitstore) DelCommit(commit *model.Commit) error {
|
|
var _, err = db.Exec(rebind(commitDeleteStmt), commit.ID)
|
|
return err
|
|
}
|
|
|
|
// KillCommits updates all pending or started commits
|
|
// in the datastore settings the status to killed.
|
|
func (db *Commitstore) KillCommits() error {
|
|
var _, err = db.Exec(rebind(commitKillStmt))
|
|
return err
|
|
}
|
|
|
|
// Commit table name in database.
|
|
const commitTable = "commits"
|
|
|
|
// SQL statement to delete a Commit by ID.
|
|
const commitDeleteStmt = `
|
|
DELETE FROM commits
|
|
WHERE commit_id = ?
|
|
`
|
|
|
|
// SQL query to retrieve the latest Commits accessible
|
|
// to a specific user account
|
|
const commitListUserQuery = `
|
|
SELECT r.repo_remote, r.repo_host, r.repo_owner, r.repo_name, c.*
|
|
FROM
|
|
commits c
|
|
,repos r
|
|
WHERE c.repo_id = r.repo_id
|
|
AND c.commit_id IN (
|
|
SELECT max(c.commit_id)
|
|
FROM
|
|
commits c
|
|
,repos r
|
|
,perms p
|
|
WHERE c.repo_id = r.repo_id
|
|
AND r.repo_id = p.repo_id
|
|
AND p.user_id = ?
|
|
GROUP BY r.repo_id
|
|
) ORDER BY c.commit_created DESC;
|
|
`
|
|
|
|
// SQL query to retrieve the ungrouped, latest Commits
|
|
// accessible to a specific user account
|
|
const commitListActivityQuery = `
|
|
SELECT r.repo_remote, r.repo_host, r.repo_owner, r.repo_name, c.*
|
|
FROM
|
|
commits c
|
|
,repos r
|
|
,perms p
|
|
WHERE c.repo_id = r.repo_id
|
|
AND r.repo_id = p.repo_id
|
|
AND p.user_id = ?
|
|
ORDER BY c.commit_created DESC
|
|
LIMIT 20
|
|
`
|
|
|
|
// SQL query to retrieve the latest Commits across all branches.
|
|
const commitListQuery = `
|
|
SELECT *
|
|
FROM commits
|
|
WHERE repo_id = ?
|
|
ORDER BY commit_id DESC
|
|
LIMIT 20
|
|
`
|
|
|
|
// SQL query to retrieve a Commit by branch and sha.
|
|
const commitShaQuery = `
|
|
SELECT *
|
|
FROM commits
|
|
WHERE repo_id = ?
|
|
AND commit_branch = ?
|
|
AND commit_sha = ?
|
|
LIMIT 1
|
|
`
|
|
|
|
// SQL query to retrieve the most recent Commit for a branch.
|
|
const commitLastQuery = `
|
|
SELECT *
|
|
FROM commits
|
|
WHERE repo_id = ?
|
|
AND commit_branch = ?
|
|
AND commit_pr = ''
|
|
ORDER BY commit_id DESC
|
|
LIMIT 1
|
|
`
|
|
|
|
// SQL query to retrieve the prior Commit (by commit_created) in the same branch and repo as the specified Commit.
|
|
const commitPriorQuery = `
|
|
SELECT *
|
|
FROM commits
|
|
WHERE repo_id = ?
|
|
AND commit_branch = ?
|
|
AND commit_created < ?
|
|
AND commit_status IN ('Success', 'Failure')
|
|
ORDER BY commit_created DESC
|
|
LIMIT 1
|
|
`
|
|
|
|
// SQL statement to cancel all running Commits.
|
|
const commitKillStmt = `
|
|
UPDATE commits SET commit_status = 'Killed'
|
|
WHERE commit_status IN ('Started', 'Pending');
|
|
`
|