158 lines
3.6 KiB
Go
158 lines
3.6 KiB
Go
package github
|
|
|
|
import (
|
|
"fmt"
|
|
"net/url"
|
|
|
|
"code.google.com/p/goauth2/oauth"
|
|
"github.com/drone/drone/shared/model"
|
|
"github.com/google/go-github/github"
|
|
)
|
|
|
|
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 successful"
|
|
DescFailure = "the build failed"
|
|
DescError = "oops, something went wrong"
|
|
)
|
|
|
|
const (
|
|
BaseURL = "https://api.github.com/"
|
|
)
|
|
|
|
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.URL,
|
|
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(rawurl, 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, _ = getEndpoint(rawurl)
|
|
}
|
|
|
|
_, _, 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)
|
|
}
|
|
|
|
// getEndpoint is a helper funcation that parsed the
|
|
// repository HTML URL to determine the API URL. It is
|
|
// intended for use with GitHub enterprise.
|
|
func getEndpoint(rawurl string) (*url.URL, error) {
|
|
uri, err := url.Parse(rawurl)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
uri.Path = "/api/v3/"
|
|
return uri, nil
|
|
}
|