1
0
mirror of https://github.com/woodpecker-ci/woodpecker.git synced 2025-12-23 22:01:08 +02:00

Move Plugins to a /plugin Directory

This commit is contained in:
Brad Rydzewski
2014-06-12 14:46:55 -07:00
parent 12fae4b62e
commit 170135cb1d
48 changed files with 17 additions and 17 deletions

View File

@@ -0,0 +1,156 @@
package github
import (
"fmt"
"net/url"
"github.com/drone/drone/plugin/remote"
"github.com/drone/go-github/github"
)
type Client struct {
config *Github
access string // user access token
}
// GetUser fetches the user by ID (login name).
func (c *Client) GetUser(login string) (*remote.User, error) {
return nil, nil
}
// GetRepos fetches all repositories that the specified
// user has access to in the remote system.
func (c *Client) GetRepos(owner string) ([]*remote.Repo, error) {
// create the github client
client := github.New(c.access)
// retrieve a list of all github repositories
repos, err := client.Repos.ListAll()
if err != nil {
return nil, err
}
// store results in common format
result := []*remote.Repo{}
// parse the hostname from the github url
githuburl, err := url.Parse(c.config.URL)
if err != nil {
return nil, err
}
// loop throught the list and convert to the standard repo format
for _, repo := range repos {
result = append(result, &remote.Repo{
ID: repo.ID,
Host: githuburl.Host,
Owner: repo.Owner.Login,
Name: repo.Name,
Kind: "git",
Clone: repo.CloneUrl,
Git: repo.GitUrl,
SSH: repo.SshUrl,
Private: repo.Private,
Push: repo.Permissions.Push,
Pull: repo.Permissions.Pull,
Admin: repo.Permissions.Admin,
})
}
return result, nil
}
// GetScript fetches the build script (.drone.yml) from the remote
// repository using the GitHub API and returns the raw file in string format.
func (c *Client) GetScript(hook *remote.Hook) (out string, err error) {
// create the github client
client := github.New(c.access)
// retrieve the .drone.yml file from GitHub
content, err := client.Contents.FindRef(hook.Owner, hook.Repo, ".drone.yml", hook.Sha)
if err != nil {
return
}
// decode the content
raw, err := content.DecodeContent()
if err != nil {
return
}
return string(raw), nil
}
// SetStatus
func (c *Client) SetStatus(owner, name, sha, status string) error {
// create the github client
client := github.New(c.access)
// convert from drone status to github status
var message string
switch status {
case "Success":
status = "success"
message = "The build succeeded on drone.io"
case "Failure":
status = "failure"
message = "The build failed on drone.io"
case "Started", "Pending":
status = "pending"
message = "The build is pending on drone.io"
default:
status = "error"
message = "The build errored on drone.io"
}
// format the build URL
// TODO we really need the branch here
// TODO we really need the drone.io hostname as well
url := fmt.Sprintf("http://beta.drone.io/%s/%s/%s/%s", owner, name, "master", sha)
// update the status
return client.Repos.CreateStatus(owner, name, status, url, message, sha)
}
// SetActive will configure a post-commit and pull-request hook
// with the remote GitHub repository using the GitHub API.
//
// It will also, optionally, add a public RSA key. This is primarily
// used for private repositories, which typically must use the Git+SSH
// protocol to clone the repository.
func (c *Client) SetActive(owner, name, hook, key string) error {
// create the github client
client := github.New(c.access)
// parse the hostname from the hook, and use this
// to name the ssh key
hookurl, err := url.Parse(hook)
if err != nil {
return err
}
// fetch the repository so that we can see if it
// is public or private.
repo, err := client.Repos.Find(owner, name)
if err != nil {
return err
}
// if the repository is private we'll need
// to upload a github key to the repository
if repo.Private {
// name the key
keyname := "drone@" + hookurl.Host
_, err := client.RepoKeys.CreateUpdate(owner, name, key, keyname)
if err != nil {
return err
}
}
// add the hook
if _, err := client.Hooks.CreateUpdate(owner, name, hook); err != nil {
return err
}
return nil
}

View File

@@ -0,0 +1,201 @@
package github
import (
"fmt"
"net/http"
"net/url"
"strconv"
"strings"
"time"
"github.com/drone/drone/plugin/remote"
"github.com/drone/drone/shared/util/httputil"
"github.com/drone/go-github/github"
"github.com/drone/go-github/oauth2"
)
var (
scope = "repo,repo:status,user:email"
state = "FqB4EbagQ2o"
)
type Github struct {
URL string `json:"url"` // https://github.com
API string `json:"api"` // https://api.github.com
Client string `json:"client"`
Secret string `json:"secret"`
Enabled bool `json:"enabled"`
}
// GetName returns the name of this remote system.
func (g *Github) GetName() string {
switch g.URL {
case "https://github.com":
return "github.com"
default:
return "enterprise.github.com"
}
}
// GetHost returns the url.Host of this remote system.
func (g *Github) GetHost() (host string) {
u, err := url.Parse(g.URL)
if err != nil {
return
}
return u.Host
}
// GetHook parses the post-commit hook from the Request body
// and returns the required data in a standard format.
func (g *Github) GetHook(r *http.Request) (*remote.Hook, error) {
// handle github ping
if r.Header.Get("X-Github-Event") == "ping" {
return nil, nil
}
// handle github pull request hook differently
if r.Header.Get("X-Github-Event") == "pull_request" {
return g.GetPullRequestHook(r)
}
// get the payload of the message
payload := r.FormValue("payload")
// parse the github Hook payload
data, err := github.ParseHook([]byte(payload))
if err != nil {
return nil, nil
}
// make sure this is being triggered because of a commit
// and not something like a tag deletion or whatever
if data.IsTag() || data.IsGithubPages() ||
data.IsHead() == false || data.IsDeleted() {
return nil, nil
}
hook := remote.Hook{}
hook.Repo = data.Repo.Name
hook.Owner = data.Repo.Owner.Login
hook.Sha = data.Head.Id
hook.Branch = data.Branch()
if len(hook.Owner) == 0 {
hook.Owner = data.Repo.Owner.Name
}
// extract the author and message from the commit
// this is kind of experimental, since I don't know
// what I'm doing here.
if data.Head != nil && data.Head.Author != nil {
hook.Message = data.Head.Message
hook.Timestamp = data.Head.Timestamp
hook.Author = data.Head.Author.Email
} else if data.Commits != nil && len(data.Commits) > 0 && data.Commits[0].Author != nil {
hook.Message = data.Commits[0].Message
hook.Timestamp = data.Commits[0].Timestamp
hook.Author = data.Commits[0].Author.Email
}
return &hook, nil
}
func (g *Github) GetPullRequestHook(r *http.Request) (*remote.Hook, error) {
payload := r.FormValue("payload")
// parse the payload to retrieve the pull-request
// hook meta-data.
data, err := github.ParsePullRequestHook([]byte(payload))
if err != nil {
return nil, err
}
// ignore these
if data.Action != "opened" && data.Action != "synchronize" {
return nil, nil
}
// TODO we should also store the pull request branch (ie from x to y)
// we can find it here: data.PullRequest.Head.Ref
hook := remote.Hook{
Owner: data.Repo.Owner.Login,
Repo: data.Repo.Name,
Sha: data.PullRequest.Head.Sha,
Branch: data.PullRequest.Base.Ref,
Author: data.PullRequest.User.Login,
Gravatar: data.PullRequest.User.GravatarId,
Timestamp: time.Now().UTC().String(),
Message: data.PullRequest.Title,
PullRequest: strconv.Itoa(data.Number),
}
if len(hook.Owner) == 0 {
hook.Owner = data.Repo.Owner.Name
}
return &hook, nil
}
// GetLogin handles authentication to third party, remote services
// and returns the required user data in a standard format.
func (g *Github) GetLogin(w http.ResponseWriter, r *http.Request) (*remote.Login, error) {
// create the oauth2 client
oauth := oauth2.Client{
RedirectURL: fmt.Sprintf("%s://%s/login/github.com", httputil.GetScheme(r), httputil.GetHost(r)),
AccessTokenURL: fmt.Sprintf("%s/login/oauth/access_token", g.URL),
AuthorizationURL: fmt.Sprintf("%s/login/oauth/authorize", g.URL),
ClientId: g.Client,
ClientSecret: g.Secret,
}
// get the OAuth code
code := r.FormValue("code")
if len(code) == 0 {
redirect := oauth.AuthorizeRedirect(scope, state)
http.Redirect(w, r, redirect, http.StatusSeeOther)
return nil, nil
}
// exchange code for an auth token
token, err := oauth.GrantToken(code)
if err != nil {
return nil, fmt.Errorf("Error granting GitHub authorization token. %s", err)
}
// create the client
client := github.New(token.AccessToken)
// get the user information
user, err := client.Users.Current()
if err != nil {
return nil, fmt.Errorf("Error retrieving currently authenticated GitHub user. %s", err)
}
// put the user data in the common format
login := remote.Login{
ID: user.ID,
Login: user.Login,
Access: token.AccessToken,
Name: user.Name,
}
// get the users primary email address
email, err := client.Emails.FindPrimary()
if err == nil {
login.Email = email.Email
}
return &login, nil
}
// GetClient returns a new Github remote client.
func (g *Github) GetClient(access, secret string) remote.Client {
return &Client{g, access}
}
// IsMatch returns true if the hostname matches the
// hostname of this remote client.
func (g *Github) IsMatch(hostname string) bool {
return strings.HasSuffix(hostname, g.URL)
}