harness-drone/plugin/notify/github/github.go
2014-08-03 21:33:47 -07:00

153 lines
3.6 KiB
Go

package github
import (
"fmt"
"net/url"
"os"
"strings"
"code.google.com/p/goauth2/oauth"
"github.com/drone/drone/shared/model"
"github.com/google/go-github/github"
)
// TODO (bradrydzewski) explore using the Repo.URL to parse the GitHub
// Entperprise Scheme+Hostname, instead of the environment variable. Is
// there any reason not to use the environment variable?
// GitHub enterprise URL
var URL = os.Getenv("GITHUB_ENTERPRISE_API")
const (
NotifyDisabled = "disabled"
NotifyFalse = "false"
NotifyOff = "off"
)
const (
StatusPending = "pending"
StatusSuccess = "success"
StatusFailure = "failure"
StatusError = "error"
)
const (
DescPending = "this build is pending"
DescSuccess = "the build was succcessful"
DescFailure = "the build failed"
DescError = "oops, something went wrong"
)
type GitHub string
// Send uses the github status API to update the build
// status in github or github enterprise.
func (g GitHub) Send(context *model.Request) error {
// a user can toggle the status api on / off
// in the .drone.yml
switch g {
case NotifyDisabled, NotifyOff, NotifyFalse:
return nil
}
// this should only be executed for GitHub and
// GitHub enterprise requests.
switch context.Repo.Remote {
case model.RemoteGithub, model.RemoteGithubEnterprise:
break
default:
return nil
}
var target = getTarget(
context.Host,
context.Repo.Host,
context.Repo.Owner,
context.Repo.Name,
context.Commit.Branch,
context.Commit.Sha,
)
return send(
context.Repo.Host,
context.Repo.Owner,
context.Repo.Name,
getStatus(context.Commit.Status),
getDesc(context.Commit.Status),
target,
context.Commit.Sha,
context.User.Access,
)
}
func send(host, owner, repo, status, desc, target, ref, token string) error {
transport := &oauth.Transport{
Token: &oauth.Token{AccessToken: token},
}
data := github.RepoStatus{
Context: github.String("Drone"),
State: github.String(status),
Description: github.String(desc),
TargetURL: github.String(target),
}
client := github.NewClient(transport.Client())
// if this is for github enterprise we need to set
// the base url. Per the documentation, we need to
// ensure there is a trailing slash.
if host != model.RemoteGithub {
client.BaseURL, _ = url.Parse(URL)
if !strings.HasSuffix(client.BaseURL.Path, "/") {
client.BaseURL.Path = client.BaseURL.Path + "/"
}
}
_, _, err := client.Repositories.CreateStatus(owner, repo, ref, &data)
return err
}
// getStatus is a helper functin that converts a Drone
// status to a GitHub 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 is a helper function that generates a description
// message for the build 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
}
}
// getTarget is a helper function that generates a URL
// for the user to click and jump to the build results.
//
// for example:
// https://drone.io/github.com/drone/drone-test-go/master/c22aec9c53
func getTarget(url, host, owner, repo, branch, commit string) string {
return fmt.Sprintf("%s/%s/%s/%s/%s/%s", url, host, owner, repo, branch, commit)
}