send build status updates to gitlab as comments on the related commit

This commit is contained in:
Kpacha 2015-08-16 18:35:33 +02:00
parent 38c61cdca9
commit 381c6d0782
3 changed files with 250 additions and 0 deletions

134
plugin/notify/gitlab.go Normal file
View file

@ -0,0 +1,134 @@
package notify
import (
"fmt"
"strconv"
"github.com/Bugagazavr/go-gitlab-client"
"github.com/drone/drone/plugin/remote/gitlab"
"github.com/drone/drone/shared/model"
)
type Gitlab struct {
SkipVerify bool `yaml:"skip_verify,omitempty"`
Started bool `yaml:"on_started,omitempty"`
Success bool `yaml:"on_success,omitempty"`
Failure bool `yaml:"on_failure,omitempty"`
}
type GitlabClient interface {
SendRepoCommitComment(id string, sha string, body string) (*gogitlab.CommitComment, error)
}
const (
StatusPending = ":raised_hand:"
StatusSuccess = ":thumbsup:"
StatusFailure = ":thumbsdown:"
StatusError = ":exclamation:"
)
const (
DescPending = "this build is pending"
DescSuccess = "the build was successful"
DescFailure = "the build failed"
DescError = "oops, something went wrong"
)
const (
PRMasterBranch = "master"
PRBadToMerge = " -> bad to merge"
PRGoodToMerge = " -> good to merge"
)
// Send uses the Gitlab repository API to comment the commit
func (g *Gitlab) Send(context *model.Request) error {
if !g.isRequested(context) {
return nil
}
return g.send(
context,
gitlab.NewClient(fmt.Sprintf("http://%s", context.Repo.Host), context.User.Access, g.SkipVerify),
)
}
func (g *Gitlab) isRequested(context *model.Request) bool {
if context.Repo.Remote != model.RemoteGitlab {
return false
}
switch context.Commit.Status {
case model.StatusStarted:
if !g.Started {
return false
}
case model.StatusSuccess:
if !g.Success {
return false
}
case model.StatusFailure, model.StatusError, model.StatusKilled:
if !g.Failure {
return false
}
}
return true
}
func (g *Gitlab) send(context *model.Request, client GitlabClient) error {
msg := fmt.Sprintf(
"[%s](%s) %s%s",
getDesc(context.Commit.Status),
getBuildUrl(context),
getStatus(context.Commit.Status),
getMergeRequestComment(context.Commit.Branch, context.Commit.Status),
)
_, err := client.SendRepoCommitComment(strconv.FormatInt(context.Repo.ID, 10), context.Commit.Sha, msg)
return err
}
// getStatus converts a Drone status to a Gitlab status.
func getStatus(status string) string {
switch status {
case model.StatusEnqueue, model.StatusStarted:
return StatusPending
case model.StatusSuccess:
return StatusSuccess
case model.StatusFailure:
return StatusFailure
case model.StatusError, model.StatusKilled:
return StatusError
default:
return StatusError
}
}
// getDesc generates a description message for the comment based on the status.
func getDesc(status string) string {
switch status {
case model.StatusEnqueue, model.StatusStarted:
return DescPending
case model.StatusSuccess:
return DescSuccess
case model.StatusFailure:
return DescFailure
case model.StatusError, model.StatusKilled:
return DescError
default:
return DescError
}
}
func getMergeRequestComment(branch, status string) string {
if branch != PRMasterBranch {
switch status {
case model.StatusSuccess:
return PRGoodToMerge
case model.StatusFailure:
return PRBadToMerge
}
}
return ""
}

View file

@ -0,0 +1,107 @@
package notify
import (
"fmt"
"testing"
"github.com/Bugagazavr/go-gitlab-client"
"github.com/drone/drone/shared/model"
)
type MockGitlabClient struct {
Comment *gogitlab.CommitComment
id string
sha string
body string
}
func (c *MockGitlabClient) SendRepoCommitComment(id string, sha string, body string) (*gogitlab.CommitComment, error) {
c.id = id
c.sha = sha
c.body = body
return c.Comment, nil
}
var gitlabClient = &MockGitlabClient{}
var gitlabSubject = &Gitlab{
SkipVerify: false,
Started: true,
Success: true,
Failure: true,
}
var gitlabRequest = &model.Request{
Host: "http://examplehost.com",
Repo: &model.Repo{
ID: 123456,
Host: "examplegit.com",
Owner: "owner",
Name: "repo",
Remote: model.RemoteGitlab,
},
Commit: &model.Commit{
Sha: "abc",
Branch: "example",
},
User: &model.User{
Access: "secret_token",
},
}
func Test_GitlabSendStarted(t *testing.T) {
gitlabRequest.Commit.Status = "Started"
expected := gogitlab.CommitComment{
Note: fmt.Sprintf("[this build is pending](%s) :raised_hand:", getBuildUrl(gitlabRequest)),
}
gitlabClient.Comment = &expected
err := gitlabSubject.send(gitlabRequest, gitlabClient)
if err != nil {
t.Errorf("Unexepected error: %s", err.Error())
}
if *gitlabClient.Comment != expected {
t.Errorf("Invalid gitlab payload. Expected: %v, got %v", expected, *gitlabClient.Comment)
}
}
func Test_GitlabSendSuccess(t *testing.T) {
gitlabRequest.Commit.Status = "Success"
expected := gogitlab.CommitComment{
Note: fmt.Sprintf("[the build was successful](%s) :thumbsup: -> good to merge", getBuildUrl(gitlabRequest)),
}
gitlabClient.Comment = &expected
err := gitlabSubject.send(gitlabRequest, gitlabClient)
if err != nil {
t.Errorf("Unexepected error: %s", err.Error())
}
if *gitlabClient.Comment != expected {
t.Errorf("Invalid gitlab payload. Expected: %v, got %v", expected, *gitlabClient.Comment)
}
}
func Test_GitlabSendFailure(t *testing.T) {
gitlabRequest.Commit.Status = "Failure"
expected := gogitlab.CommitComment{
Note: fmt.Sprintf("[the build failed](%s) :thumbsdown: -> bad to merge", getBuildUrl(gitlabRequest)),
}
gitlabClient.Comment = &expected
err := gitlabSubject.send(gitlabRequest, gitlabClient)
if err != nil {
t.Errorf("Unexepected error: %s", err.Error())
}
if *gitlabClient.Comment != expected {
t.Errorf("Invalid gitlab payload. Expected: %v, got %v", expected, *gitlabClient.Comment)
}
}

View file

@ -31,6 +31,7 @@ type Notification struct {
Gitter *Gitter `yaml:"gitter,omitempty"`
Flowdock *flowdock.Flowdock `yaml:"flowdock,omitempty"`
KatoIM *katoim.KatoIM `yaml:"katoim,omitempty"`
Gitlab *Gitlab `yaml:"gitlab,omitempty"`
GitHub github.GitHub `yaml:"--"`
}
@ -100,6 +101,14 @@ func (n *Notification) Send(context *model.Request) error {
}
}
// send Gitlab notifications
if n.Gitlab != nil {
err := n.Gitlab.Send(context)
if err != nil {
log.Println(err)
}
}
// send email notifications
// TODO (bradrydzewski) need to improve this code
githubStatus := new(github.GitHub)