Merge remote-tracking branch 'origin'
This commit is contained in:
commit
ba5ec0ae37
12 changed files with 372 additions and 22 deletions
16
README.md
16
README.md
|
@ -10,19 +10,7 @@ Drone's prime directive is to help teams [ship code like GitHub](https://github.
|
|||
|
||||
### Documentation
|
||||
|
||||
Drone documentation is organized into several categories:
|
||||
|
||||
* [Setup Guide](http://readme.drone.io/setup/overview)
|
||||
* [Build Guide](http://readme.drone.io/usage/overview)
|
||||
* [Plugin Guide](http://readme.drone.io/devs/plugins)
|
||||
* [CLI Reference](http://readme.drone.io/devs/cli/)
|
||||
* [API Reference](http://readme.drone.io/devs/api/builds)
|
||||
|
||||
### Documentation for 0.5 (unstable)
|
||||
|
||||
If you are using the 0.5 unstable release (master branch) please see the updated [documentation](http://readme.drone.io/0.5).
|
||||
|
||||
|
||||
Documentation is published to [readme.drone.io](http://readme.drone.io)
|
||||
|
||||
### Community, Help
|
||||
|
||||
|
@ -30,7 +18,7 @@ Contributions, questions, and comments are welcomed and encouraged. Drone develo
|
|||
|
||||
### Installation
|
||||
|
||||
Please see our [installation guide](http://readme.drone.io/setup/overview) to install the official Docker image.
|
||||
Please see our [installation guide](http://readme.drone.io/admin/) to install the official Docker image.
|
||||
|
||||
### From Source
|
||||
|
||||
|
|
|
@ -30,12 +30,13 @@ func getRepo(c *gin.Context) {
|
|||
}
|
||||
|
||||
func getRepoFile(c *gin.Context) {
|
||||
switch c.Param("file") {
|
||||
case "file_not_found":
|
||||
if c.Param("file") == "file_not_found" {
|
||||
c.String(404, "")
|
||||
default:
|
||||
}
|
||||
if c.Param("commit") == "v1.0.0" || c.Param("commit") == "9ecad50" {
|
||||
c.String(200, repoFilePayload)
|
||||
}
|
||||
c.String(404, "")
|
||||
}
|
||||
|
||||
func createRepoHook(c *gin.Context) {
|
||||
|
|
|
@ -83,3 +83,55 @@ var HookPushTag = `{
|
|||
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
|
||||
}
|
||||
}`
|
||||
|
||||
// HookPullRequest is a sample pull_request webhook payload
|
||||
var HookPullRequest = `{
|
||||
"action": "opened",
|
||||
"number": 1,
|
||||
"pull_request": {
|
||||
"html_url": "http://gogs.golang.org/gordon/hello-world/pull/1",
|
||||
"state": "open",
|
||||
"title": "Update the README with new information",
|
||||
"body": "please merge",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "gordon",
|
||||
"full_name": "Gordon the Gopher",
|
||||
"email": "gordon@golang.org",
|
||||
"avatar_url": "http://gogs.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
|
||||
},
|
||||
"base": {
|
||||
"label": "master",
|
||||
"ref": "master",
|
||||
"sha": "9353195a19e45482665306e466c832c46560532d"
|
||||
},
|
||||
"head": {
|
||||
"label": "feature/changes",
|
||||
"ref": "feature/changes",
|
||||
"sha": "0d1a26e67d8f5eaf1f6ba5c57fc3c7d91ac0fd1c"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"id": 35129377,
|
||||
"name": "hello-world",
|
||||
"full_name": "gordon/hello-world",
|
||||
"owner": {
|
||||
"id": 1,
|
||||
"username": "gordon",
|
||||
"full_name": "Gordon the Gopher",
|
||||
"email": "gordon@golang.org",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
|
||||
},
|
||||
"private": true,
|
||||
"html_url": "http://gogs.golang.org/gordon/hello-world",
|
||||
"clone_url": "https://gogs.golang.org/gordon/hello-world.git",
|
||||
"default_branch": "master"
|
||||
},
|
||||
"sender": {
|
||||
"id": 1,
|
||||
"username": "gordon",
|
||||
"full_name": "Gordon the Gopher",
|
||||
"email": "gordon@golang.org",
|
||||
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
|
||||
}
|
||||
}`
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
|
||||
"github.com/drone/drone/model"
|
||||
"github.com/drone/drone/remote"
|
||||
|
@ -176,7 +177,14 @@ func (c *client) File(u *model.User, r *model.Repo, b *model.Build, f string) ([
|
|||
client := c.newClientToken(u.Token)
|
||||
buildRef := b.Commit
|
||||
if buildRef == "" {
|
||||
buildRef = b.Ref
|
||||
// Remove refs/tags or refs/heads, Gogs needs a short ref
|
||||
buildRef = strings.TrimPrefix(
|
||||
strings.TrimPrefix(
|
||||
b.Ref,
|
||||
"refs/heads/",
|
||||
),
|
||||
"refs/tags/",
|
||||
)
|
||||
}
|
||||
cfg, err := client.GetFile(r.Owner, r.Name, buildRef, f)
|
||||
return cfg, err
|
||||
|
|
|
@ -128,6 +128,12 @@ func Test_gogs(t *testing.T) {
|
|||
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }")
|
||||
})
|
||||
|
||||
g.It("Should return a repository file from a ref", func() {
|
||||
raw, err := c.File(fakeUser, fakeRepo, fakeBuildWithRef, ".drone.yml")
|
||||
g.Assert(err == nil).IsTrue()
|
||||
g.Assert(string(raw)).Equal("{ platform: linux/amd64 }")
|
||||
})
|
||||
|
||||
g.Describe("Given an authentication request", func() {
|
||||
g.It("Should redirect to login form")
|
||||
g.It("Should create an access token")
|
||||
|
@ -178,4 +184,8 @@ var (
|
|||
fakeBuild = &model.Build{
|
||||
Commit: "9ecad50",
|
||||
}
|
||||
|
||||
fakeBuildWithRef = &model.Build{
|
||||
Ref: "refs/tags/v1.0.0",
|
||||
}
|
||||
)
|
||||
|
|
|
@ -112,6 +112,30 @@ func buildFromTag(hook *pushHook) *model.Build {
|
|||
}
|
||||
}
|
||||
|
||||
// helper function that extracts the Build data from a Gogs pull_request hook
|
||||
func buildFromPullRequest(hook *pullRequestHook) *model.Build {
|
||||
avatar := expandAvatar(
|
||||
hook.Repo.URL,
|
||||
fixMalformedAvatar(hook.PullRequest.User.Avatar),
|
||||
)
|
||||
build := &model.Build{
|
||||
Event: model.EventPull,
|
||||
Commit: hook.PullRequest.Head.Sha,
|
||||
Link: hook.PullRequest.URL,
|
||||
Ref: fmt.Sprintf("refs/pull/%d/head", hook.Number),
|
||||
Branch: hook.PullRequest.Base.Ref,
|
||||
Message: hook.PullRequest.Title,
|
||||
Author: hook.PullRequest.User.Username,
|
||||
Avatar: avatar,
|
||||
Title: hook.PullRequest.Title,
|
||||
Refspec: fmt.Sprintf("%s:%s",
|
||||
hook.PullRequest.Head.Ref,
|
||||
hook.PullRequest.Base.Ref,
|
||||
),
|
||||
}
|
||||
return build
|
||||
}
|
||||
|
||||
// helper function that extracts the Repository data from a Gogs push hook
|
||||
func repoFromPush(hook *pushHook) *model.Repo {
|
||||
return &model.Repo{
|
||||
|
@ -122,6 +146,16 @@ func repoFromPush(hook *pushHook) *model.Repo {
|
|||
}
|
||||
}
|
||||
|
||||
// helper function that extracts the Repository data from a Gogs pull_request hook
|
||||
func repoFromPullRequest(hook *pullRequestHook) *model.Repo {
|
||||
return &model.Repo{
|
||||
Name: hook.Repo.Name,
|
||||
Owner: hook.Repo.Owner.Username,
|
||||
FullName: hook.Repo.FullName,
|
||||
Link: hook.Repo.URL,
|
||||
}
|
||||
}
|
||||
|
||||
// helper function that parses a push hook from a read closer.
|
||||
func parsePush(r io.Reader) (*pushHook, error) {
|
||||
push := new(pushHook)
|
||||
|
@ -129,6 +163,12 @@ func parsePush(r io.Reader) (*pushHook, error) {
|
|||
return push, err
|
||||
}
|
||||
|
||||
func parsePullRequest(r io.Reader) (*pullRequestHook, error) {
|
||||
pr := new(pullRequestHook)
|
||||
err := json.NewDecoder(r).Decode(pr)
|
||||
return pr, err
|
||||
}
|
||||
|
||||
// fixMalformedAvatar is a helper function that fixes an avatar url if malformed
|
||||
// (currently a known bug with gogs)
|
||||
func fixMalformedAvatar(url string) string {
|
||||
|
|
|
@ -53,6 +53,32 @@ func Test_parse(t *testing.T) {
|
|||
g.Assert(hook.Sender.Avatar).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
|
||||
})
|
||||
|
||||
g.It("Should parse pull_request hook payload", func() {
|
||||
buf := bytes.NewBufferString(fixtures.HookPullRequest)
|
||||
hook, err := parsePullRequest(buf)
|
||||
g.Assert(err == nil).IsTrue()
|
||||
g.Assert(hook.Action).Equal("opened")
|
||||
g.Assert(hook.Number).Equal(int64(1))
|
||||
|
||||
g.Assert(hook.Repo.Name).Equal("hello-world")
|
||||
g.Assert(hook.Repo.URL).Equal("http://gogs.golang.org/gordon/hello-world")
|
||||
g.Assert(hook.Repo.FullName).Equal("gordon/hello-world")
|
||||
g.Assert(hook.Repo.Owner.Email).Equal("gordon@golang.org")
|
||||
g.Assert(hook.Repo.Owner.Username).Equal("gordon")
|
||||
g.Assert(hook.Repo.Private).Equal(true)
|
||||
g.Assert(hook.Sender.Username).Equal("gordon")
|
||||
g.Assert(hook.Sender.Avatar).Equal("https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
|
||||
|
||||
g.Assert(hook.PullRequest.Title).Equal("Update the README with new information")
|
||||
g.Assert(hook.PullRequest.Body).Equal("please merge")
|
||||
g.Assert(hook.PullRequest.State).Equal("open")
|
||||
g.Assert(hook.PullRequest.User.Username).Equal("gordon")
|
||||
g.Assert(hook.PullRequest.Base.Label).Equal("master")
|
||||
g.Assert(hook.PullRequest.Base.Ref).Equal("master")
|
||||
g.Assert(hook.PullRequest.Head.Label).Equal("feature/changes")
|
||||
g.Assert(hook.PullRequest.Head.Ref).Equal("feature/changes")
|
||||
})
|
||||
|
||||
g.It("Should return a Build struct from a push hook", func() {
|
||||
buf := bytes.NewBufferString(fixtures.HookPush)
|
||||
hook, _ := parsePush(buf)
|
||||
|
@ -78,6 +104,31 @@ func Test_parse(t *testing.T) {
|
|||
g.Assert(repo.Link).Equal(hook.Repo.URL)
|
||||
})
|
||||
|
||||
g.It("Should return a Build struct from a pull_request hook", func() {
|
||||
buf := bytes.NewBufferString(fixtures.HookPullRequest)
|
||||
hook, _ := parsePullRequest(buf)
|
||||
build := buildFromPullRequest(hook)
|
||||
g.Assert(build.Event).Equal(model.EventPull)
|
||||
g.Assert(build.Commit).Equal(hook.PullRequest.Head.Sha)
|
||||
g.Assert(build.Ref).Equal("refs/pull/1/head")
|
||||
g.Assert(build.Link).Equal(hook.PullRequest.URL)
|
||||
g.Assert(build.Branch).Equal("master")
|
||||
g.Assert(build.Message).Equal(hook.PullRequest.Title)
|
||||
g.Assert(build.Avatar).Equal("http://1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
|
||||
g.Assert(build.Author).Equal(hook.PullRequest.User.Username)
|
||||
|
||||
})
|
||||
|
||||
g.It("Should return a Repo struct from a pull_request hook", func() {
|
||||
buf := bytes.NewBufferString(fixtures.HookPullRequest)
|
||||
hook, _ := parsePullRequest(buf)
|
||||
repo := repoFromPullRequest(hook)
|
||||
g.Assert(repo.Name).Equal(hook.Repo.Name)
|
||||
g.Assert(repo.Owner).Equal(hook.Repo.Owner.Username)
|
||||
g.Assert(repo.FullName).Equal("gordon/hello-world")
|
||||
g.Assert(repo.Link).Equal(hook.Repo.URL)
|
||||
})
|
||||
|
||||
g.It("Should return a Perm struct from a Gogs Perm", func() {
|
||||
perms := []gogs.Permission{
|
||||
{true, true, true},
|
||||
|
|
|
@ -8,9 +8,15 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
hookEvent = "X-Gogs-Event"
|
||||
hookPush = "push"
|
||||
hookCreated = "create"
|
||||
hookEvent = "X-Gogs-Event"
|
||||
hookPush = "push"
|
||||
hookCreated = "create"
|
||||
hookPullRequest = "pull_request"
|
||||
|
||||
actionOpen = "opened"
|
||||
actionSync = "synchronize"
|
||||
|
||||
stateOpen = "open"
|
||||
|
||||
refBranch = "branch"
|
||||
refTag = "tag"
|
||||
|
@ -24,6 +30,8 @@ func parseHook(r *http.Request) (*model.Repo, *model.Build, error) {
|
|||
return parsePushHook(r.Body)
|
||||
case hookCreated:
|
||||
return parseCreatedHook(r.Body)
|
||||
case hookPullRequest:
|
||||
return parsePullRequestHook(r.Body)
|
||||
}
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
@ -72,3 +80,28 @@ func parseCreatedHook(payload io.Reader) (*model.Repo, *model.Build, error) {
|
|||
build = buildFromTag(push)
|
||||
return repo, build, err
|
||||
}
|
||||
|
||||
// parsePullRequestHook parses a pull_request hook and returns the Repo and Build details.
|
||||
func parsePullRequestHook(payload io.Reader) (*model.Repo, *model.Build, error) {
|
||||
var (
|
||||
repo *model.Repo
|
||||
build *model.Build
|
||||
)
|
||||
|
||||
pr, err := parsePullRequest(payload)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// Don't trigger builds for non-code changes, or if PR is not open
|
||||
if pr.Action != actionOpen && pr.Action != actionSync {
|
||||
return nil, nil, nil
|
||||
}
|
||||
if pr.PullRequest.State != stateOpen {
|
||||
return nil, nil, nil
|
||||
}
|
||||
|
||||
repo = repoFromPullRequest(pr)
|
||||
build = buildFromPullRequest(pr)
|
||||
return repo, build, err
|
||||
}
|
||||
|
|
|
@ -40,3 +40,85 @@ type pushHook struct {
|
|||
Avatar string `json:"avatar_url"`
|
||||
} `json:"sender"`
|
||||
}
|
||||
|
||||
type pullRequestHook struct {
|
||||
Action string `json:"action"`
|
||||
Number int64 `json:"number"`
|
||||
PullRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
User struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
} `json:"user"`
|
||||
Title string `json:"title"`
|
||||
Body string `json:"body"`
|
||||
Labels []string `json:"labels"`
|
||||
State string `json:"state"`
|
||||
URL string `json:"html_url"`
|
||||
Mergeable bool `json:"mergeable"`
|
||||
Merged bool `json:"merged"`
|
||||
MergeBase string `json:"merge_base"`
|
||||
Base struct {
|
||||
Label string `json:"label"`
|
||||
Ref string `json:"ref"`
|
||||
Sha string `json:"sha"`
|
||||
Repo struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
URL string `json:"html_url"`
|
||||
Private bool `json:"private"`
|
||||
Owner struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
} `json:"owner"`
|
||||
} `json:"repo"`
|
||||
} `json:"base"`
|
||||
Head struct {
|
||||
Label string `json:"label"`
|
||||
Ref string `json:"ref"`
|
||||
Sha string `json:"sha"`
|
||||
Repo struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
URL string `json:"html_url"`
|
||||
Private bool `json:"private"`
|
||||
Owner struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
} `json:"owner"`
|
||||
} `json:"repo"`
|
||||
} `json:"head"`
|
||||
} `json:"pull_request"`
|
||||
Repo struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
FullName string `json:"full_name"`
|
||||
URL string `json:"html_url"`
|
||||
Private bool `json:"private"`
|
||||
Owner struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
} `json:"owner"`
|
||||
} `json:"repository"`
|
||||
Sender struct {
|
||||
ID int64 `json:"id"`
|
||||
Username string `json:"username"`
|
||||
Name string `json:"full_name"`
|
||||
Email string `json:"email"`
|
||||
Avatar string `json:"avatar_url"`
|
||||
} `json:"sender"`
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ func Broker(cli *cli.Context) gin.HandlerFunc {
|
|||
|
||||
// setup broker logging.
|
||||
log := redlog.New(os.Stderr)
|
||||
log.SetLevel(0)
|
||||
log.SetLevel(2)
|
||||
logger.SetLogger(log)
|
||||
if cli.Bool("broker-debug") {
|
||||
log.SetLevel(1)
|
||||
|
|
|
@ -153,6 +153,21 @@ func Load(middleware ...gin.HandlerFunc) http.Handler {
|
|||
agents.GET("", server.GetAgents)
|
||||
}
|
||||
|
||||
debug := e.Group("/api/debug")
|
||||
{
|
||||
debug.Use(session.MustAdmin())
|
||||
debug.GET("/pprof/", server.IndexHandler())
|
||||
debug.GET("/pprof/heap", server.HeapHandler())
|
||||
debug.GET("/pprof/goroutine", server.GoroutineHandler())
|
||||
debug.GET("/pprof/block", server.BlockHandler())
|
||||
debug.GET("/pprof/threadcreate", server.ThreadCreateHandler())
|
||||
debug.GET("/pprof/cmdline", server.CmdlineHandler())
|
||||
debug.GET("/pprof/profile", server.ProfileHandler())
|
||||
debug.GET("/pprof/symbol", server.SymbolHandler())
|
||||
debug.POST("/pprof/symbol", server.SymbolHandler())
|
||||
debug.GET("/pprof/trace", server.TraceHandler())
|
||||
}
|
||||
|
||||
// DELETE THESE
|
||||
// gitlab := e.Group("/gitlab/:owner/:name")
|
||||
// {
|
||||
|
|
70
server/debug.go
Normal file
70
server/debug.go
Normal file
|
@ -0,0 +1,70 @@
|
|||
package server
|
||||
|
||||
import (
|
||||
"net/http/pprof"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// IndexHandler will pass the call from /debug/pprof to pprof
|
||||
func IndexHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Index(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// HeapHandler will pass the call from /debug/pprof/heap to pprof
|
||||
func HeapHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Handler("heap").ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// GoroutineHandler will pass the call from /debug/pprof/goroutine to pprof
|
||||
func GoroutineHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Handler("goroutine").ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// BlockHandler will pass the call from /debug/pprof/block to pprof
|
||||
func BlockHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Handler("block").ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// ThreadCreateHandler will pass the call from /debug/pprof/threadcreate to pprof
|
||||
func ThreadCreateHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Handler("threadcreate").ServeHTTP(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// CmdlineHandler will pass the call from /debug/pprof/cmdline to pprof
|
||||
func CmdlineHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Cmdline(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// ProfileHandler will pass the call from /debug/pprof/profile to pprof
|
||||
func ProfileHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Profile(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// SymbolHandler will pass the call from /debug/pprof/symbol to pprof
|
||||
func SymbolHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Symbol(c.Writer, c.Request)
|
||||
}
|
||||
}
|
||||
|
||||
// TraceHandler will pass the call from /debug/pprof/trace to pprof
|
||||
func TraceHandler() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
pprof.Trace(c.Writer, c.Request)
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue