mirror of
https://github.com/woodpecker-ci/woodpecker.git
synced 2024-11-23 18:31:00 +00:00
send build status updates to gitlab as comments on the related commit
This commit is contained in:
parent
38c61cdca9
commit
381c6d0782
3 changed files with 250 additions and 0 deletions
134
plugin/notify/gitlab.go
Normal file
134
plugin/notify/gitlab.go
Normal 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 ""
|
||||
}
|
107
plugin/notify/gitlab_test.go
Normal file
107
plugin/notify/gitlab_test.go
Normal 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)
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue