2014-06-05 00:25:38 +03:00
|
|
|
package handler
|
|
|
|
|
|
|
|
import (
|
|
|
|
"net/http"
|
|
|
|
|
2014-06-13 02:41:04 +03:00
|
|
|
"github.com/drone/drone/server/database"
|
2014-06-10 01:47:35 +03:00
|
|
|
"github.com/drone/drone/server/queue"
|
2014-06-13 02:41:04 +03:00
|
|
|
"github.com/drone/drone/shared/model"
|
2014-06-05 00:25:38 +03:00
|
|
|
"github.com/gorilla/pat"
|
|
|
|
)
|
|
|
|
|
|
|
|
type HookHandler struct {
|
2014-06-13 02:41:04 +03:00
|
|
|
users database.UserManager
|
|
|
|
repos database.RepoManager
|
|
|
|
commits database.CommitManager
|
2014-06-13 03:17:59 +03:00
|
|
|
conf database.ConfigManager
|
2014-06-10 01:47:35 +03:00
|
|
|
queue *queue.Queue
|
2014-06-05 00:25:38 +03:00
|
|
|
}
|
|
|
|
|
2014-06-13 03:17:59 +03:00
|
|
|
func NewHookHandler(users database.UserManager, repos database.RepoManager, commits database.CommitManager, conf database.ConfigManager, queue *queue.Queue) *HookHandler {
|
|
|
|
return &HookHandler{users, repos, commits, conf, queue}
|
2014-06-05 00:25:38 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
// PostHook receives a post-commit hook from GitHub, Bitbucket, etc
|
|
|
|
// GET /hook/:host
|
|
|
|
func (h *HookHandler) PostHook(w http.ResponseWriter, r *http.Request) error {
|
|
|
|
host := r.FormValue(":host")
|
|
|
|
|
|
|
|
// get the remote system's client.
|
2014-06-13 03:17:59 +03:00
|
|
|
remote := h.conf.Find().GetRemote(host)
|
2014-06-05 00:25:38 +03:00
|
|
|
if remote == nil {
|
|
|
|
return notFound{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// parse the hook payload
|
|
|
|
hook, err := remote.GetHook(r)
|
|
|
|
if err != nil {
|
|
|
|
return badRequest{err}
|
|
|
|
}
|
|
|
|
|
|
|
|
// in some cases we have neither a hook nor error. An example
|
|
|
|
// would be GitHub sending a ping request to the URL, in which
|
|
|
|
// case we'll just exit quiely with an 'OK'
|
|
|
|
if hook == nil {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2014-06-12 22:44:19 +03:00
|
|
|
//fmt.Printf("%#v", hook)
|
|
|
|
|
2014-06-05 00:25:38 +03:00
|
|
|
// fetch the repository from the database
|
2014-06-10 01:47:35 +03:00
|
|
|
repo, err := h.repos.FindName(remote.GetHost(), hook.Owner, hook.Repo)
|
2014-06-05 00:25:38 +03:00
|
|
|
if err != nil {
|
|
|
|
return notFound{}
|
|
|
|
}
|
|
|
|
|
|
|
|
if repo.Active == false ||
|
|
|
|
(repo.PostCommit == false && len(hook.PullRequest) == 0) ||
|
|
|
|
(repo.PullRequest == false && len(hook.PullRequest) != 0) {
|
|
|
|
w.WriteHeader(http.StatusOK)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// fetch the user from the database that owns this repo
|
|
|
|
user, err := h.users.Find(repo.UserID)
|
|
|
|
if err != nil {
|
|
|
|
return notFound{}
|
|
|
|
}
|
|
|
|
|
|
|
|
// featch the .drone.yml file from the database
|
|
|
|
client := remote.GetClient(user.Access, user.Secret)
|
2014-06-12 03:42:49 +03:00
|
|
|
yml, err := client.GetScript(hook)
|
2014-06-05 00:25:38 +03:00
|
|
|
if err != nil {
|
|
|
|
return badRequest{err}
|
|
|
|
}
|
|
|
|
|
2014-06-13 02:41:04 +03:00
|
|
|
c := model.Commit{
|
2014-06-05 00:25:38 +03:00
|
|
|
RepoID: repo.ID,
|
2014-06-13 02:41:04 +03:00
|
|
|
Status: model.StatusEnqueue,
|
2014-06-05 00:25:38 +03:00
|
|
|
Sha: hook.Sha,
|
|
|
|
Branch: hook.Branch,
|
|
|
|
PullRequest: hook.PullRequest,
|
|
|
|
Timestamp: hook.Timestamp,
|
2014-06-12 03:42:49 +03:00
|
|
|
Message: hook.Message,
|
|
|
|
Config: yml}
|
2014-06-05 00:25:38 +03:00
|
|
|
c.SetAuthor(hook.Author)
|
|
|
|
// inser the commit into the database
|
|
|
|
if err := h.commits.Insert(&c); err != nil {
|
|
|
|
return badRequest{err}
|
|
|
|
}
|
|
|
|
|
2014-06-12 22:44:19 +03:00
|
|
|
//fmt.Printf("%s", yml)
|
2014-06-05 00:25:38 +03:00
|
|
|
|
|
|
|
// drop the items on the queue
|
2014-06-12 03:42:49 +03:00
|
|
|
h.queue.Add(&queue.BuildTask{Repo: repo, Commit: &c})
|
2014-06-05 00:25:38 +03:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *HookHandler) Register(r *pat.Router) {
|
|
|
|
r.Post("/hook/{host}", errorHandler(h.PostHook))
|
|
|
|
r.Put("/hook/{host}", errorHandler(h.PostHook))
|
|
|
|
}
|