Merge pull request #1874 from bradrydzewski/master

Improve Gogs tag implementation
This commit is contained in:
Brad Rydzewski 2016-11-25 17:13:03 +01:00 committed by GitHub
commit a8b59c331a
7 changed files with 163 additions and 255 deletions

View file

@ -1,6 +1,6 @@
package fixtures
// old version ?
// Sample Gogs push hook
var HookPush = `
{
"ref": "refs/heads/master",
@ -22,7 +22,10 @@ var HookPush = `
"repository": {
"id": 1,
"name": "hello-world",
"url": "http://gogs.golang.org/gordon/hello-world",
"full_name": "gordon/hello-world",
"html_url": "http://gogs.golang.org/gordon/hello-world",
"ssh_url": "git@gogs.golang.org:gordon/hello-world.git",
"clone_url": "http://gogs.golang.org/gordon/hello-world.git",
"description": "",
"website": "",
"watchers": 1,
@ -46,222 +49,37 @@ var HookPush = `
}
`
// Sampled from Gogs version 0.9.97
// X-Gogs-Event: push
var HookPushNew = `
{
"secret": "a_secret",
"ref": "refs/heads/master",
"before": "117b1990205dbc6395656ef1ed2125719aa7f4d3",
"after": "7d7605add378b55e6154d96b3e0957d392e2cc14",
"compare_url": "http://cdb:3000/org1/test3/compare/117b1990205dbc6395656ef1ed2125719aa7f4d3...7d7605add378b55e6154d96b3e0957d392e2cc14",
"commits": [
{
"id": "7d7605add378b55e6154d96b3e0957d392e2cc14",
"message": "Capitalize\n",
"url": "http://cdb:3000/org1/test3/commit/7d7605add378b55e6154d96b3e0957d392e2cc14",
"author": {
"name": "Sandro Santilli",
"email": "strk@kbt.io",
"username": "strk"
},
"committer": {
"name": "Sandro Santilli",
"email": "strk@kbt.io",
"username": "strk"
},
"timestamp": "2016-08-31T22:51:59+02:00"
},
{
"id": "85800d8ecf8107626dc43a0cbdf218c31cd04779",
"message": "dot\n",
"url": "http://cdb:3000/org1/test3/commit/85800d8ecf8107626dc43a0cbdf218c31cd04779",
"author": {
"name": "Sandro Santilli",
"email": "strk@kbt.io",
"username": "strk"
},
"committer": {
"name": "Sandro Santilli",
"email": "strk@kbt.io",
"username": "strk"
},
"timestamp": "2016-08-31T22:46:53+02:00"
}
],
// Sample Gogs tag hook
var HookPushTag = `{
"secret": "l26Un7G7HXogLAvsyf2hOA4EMARSTsR3",
"ref": "v1.0.0",
"ref_type": "tag",
"repository": {
"id": 5,
"id": 1,
"owner": {
"id": 5,
"username": "org1",
"full_name": "org1",
"email": "",
"avatar_url": "http://cdb:3000/avatars/5"
},
"name": "test3",
"full_name": "org1/test3",
"description": "just a test",
"private": false,
"fork": false,
"html_url": "http://cdb:3000/org1/test3",
"ssh_url": "strk@git.osgeo.org:org1/test3.git",
"clone_url": "http://cdb:3000/org1/test3.git",
"website": "",
"stars_count": 0,
"forks_count": 1,
"watchers_count": 2,
"open_issues_count": 0,
"default_branch": "master",
"created_at": "2016-08-31T22:45:16+02:00",
"updated_at": "2016-08-31T22:45:31+02:00"
},
"pusher": {
"id": 1,
"username": "strk",
"full_name": "",
"email": "strk@kbt.io",
"avatar_url": "https://avatars.kbt.io/avatar/fe2a9e759730ee64c44bf8901bf4ccc3"
},
"sender": {
"id": 1,
"username": "strk",
"full_name": "",
"email": "strk@kbt.io",
"avatar_url": "https://avatars.kbt.io/avatar/fe2a9e759730ee64c44bf8901bf4ccc3"
}
}
`
// Sampled from Gogs version 0.9.97
// X-Gogs-Event: pull_request
var HookPullRequestOpenNew = `
{
"secret": "a_secret",
"action": "opened",
"number": 1,
"pull_request": {
"id": 2,
"number": 1,
"user": {
"id": 1,
"username": "strk",
"full_name": "",
"email": "strk@kbt.io",
"avatar_url": "https://avatars.kbt.io/avatar/fe2a9e759730ee64c44bf8901bf4ccc3"
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
},
"title": "dot",
"body": "could you figure",
"labels": [],
"milestone": null,
"assignee": null,
"state": "open",
"comments": 0,
"html_url": "http://cdb:3000/org1/test3/pulls/1",
"mergeable": true,
"merged": false,
"merged_at": null,
"merge_commit_sha": null,
"merged_by": null
},
"repository": {
"id": 5,
"owner": {
"id": 5,
"username": "org1",
"full_name": "org1",
"email": "",
"avatar_url": "http://cdb:3000/avatars/5"
},
"name": "test3",
"full_name": "org1/test3",
"description": "just a test",
"private": false,
"name": "hello-world",
"full_name": "gordon/hello-world",
"description": "",
"private": true,
"fork": false,
"html_url": "http://cdb:3000/org1/test3",
"ssh_url": "strk@git.osgeo.org:org1/test3.git",
"clone_url": "http://cdb:3000/org1/test3.git",
"website": "",
"stars_count": 0,
"forks_count": 1,
"watchers_count": 2,
"open_issues_count": 0,
"html_url": "http://gogs.golang.org/gordon/hello-world",
"ssh_url": "git@gogs.golang.org:gordon/hello-world.git",
"clone_url": "http://gogs.golang.org/gordon/hello-world.git",
"default_branch": "master",
"created_at": "2016-08-31T22:45:16+02:00",
"updated_at": "2016-08-31T22:45:31+02:00"
"created_at": "2015-10-22T19:32:44Z",
"updated_at": "2016-11-24T13:37:16Z"
},
"sender": {
"id": 1,
"username": "strk",
"full_name": "",
"email": "strk@kbt.io",
"avatar_url": "https://avatars.kbt.io/avatar/fe2a9e759730ee64c44bf8901bf4ccc3"
"username": "gordon",
"full_name": "Gordon the Gopher",
"email": "gordon@golang.org",
"avatar_url": "https://secure.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87"
}
}
`
// Sampled from Gogs version 0.9.97
// X-Gogs-Event: pull_request
var HookPullRequestSynchronize = `
{
"secret": "a_secret",
"action": "synchronized",
"number": 1,
"pull_request": {
"id": 2,
"number": 1,
"user": {
"id": 1,
"username": "strk",
"full_name": "",
"email": "strk@kbt.io",
"avatar_url": "https://avatars.kbt.io/avatar/fe2a9e759730ee64c44bf8901bf4ccc3"
},
"title": "dot",
"body": "could you figure",
"labels": [],
"milestone": null,
"assignee": null,
"state": "open",
"comments": 0,
"html_url": "http://cdb:3000/org1/test3/pulls/1",
"mergeable": true,
"merged": false,
"merged_at": null,
"merge_commit_sha": null,
"merged_by": null
},
"repository": {
"id": 5,
"owner": {
"id": 5,
"username": "org1",
"full_name": "org1",
"email": "",
"avatar_url": "http://cdb:3000/avatars/5"
},
"name": "test3",
"full_name": "org1/test3",
"description": "just a test",
"private": false,
"fork": false,
"html_url": "http://cdb:3000/org1/test3",
"ssh_url": "strk@git.osgeo.org:org1/test3.git",
"clone_url": "http://cdb:3000/org1/test3.git",
"website": "",
"stars_count": 0,
"forks_count": 1,
"watchers_count": 2,
"open_issues_count": 0,
"default_branch": "master",
"created_at": "2016-08-31T22:45:16+02:00",
"updated_at": "2016-08-31T22:45:31+02:00"
},
"sender": {
"id": 1,
"username": "strk",
"full_name": "",
"email": "strk@kbt.io",
"avatar_url": "https://avatars.kbt.io/avatar/fe2a9e759730ee64c44bf8901bf4ccc3"
}
}
`
}`

View file

@ -232,22 +232,7 @@ func (c *client) Deactivate(u *model.User, r *model.Repo, link string) error {
// Hook parses the incoming Gogs hook and returns the Repository and Build
// details. If the hook is unsupported nil values are returned.
func (c *client) Hook(r *http.Request) (*model.Repo, *model.Build, error) {
var (
err error
repo *model.Repo
build *model.Build
)
switch r.Header.Get("X-Gogs-Event") {
case "push":
var push *pushHook
push, err = parsePush(r.Body)
if err == nil && push.RefType != "branch" {
repo = repoFromPush(push)
build = buildFromPush(push)
}
}
return repo, build, err
return parseHook(r)
}
// helper function to return the Gogs client

View file

@ -70,43 +70,54 @@ func buildFromPush(hook *pushHook) *model.Build {
hook.Repo.URL,
fixMalformedAvatar(hook.Sender.Avatar),
)
var eventType string
var message string
switch {
case hook.RefType == "tag":
eventType = model.EventTag
message = "Tag " + hook.Ref
default:
eventType = model.EventPush
message = hook.Commits[0].Message
author := hook.Sender.Login
if author == "" {
author = hook.Sender.Username
}
return &model.Build{
Event: eventType,
Event: model.EventPush,
Commit: hook.After,
Ref: hook.Ref,
Link: hook.Compare,
Branch: strings.TrimPrefix(hook.Ref, "refs/heads/"),
Message: message,
Message: hook.Commits[0].Message,
Avatar: avatar,
Author: hook.Sender.Login,
Author: author,
Timestamp: time.Now().UTC().Unix(),
}
}
// helper function that extracts the Build data from a Gogs tag hook
func buildFromTag(hook *pushHook) *model.Build {
avatar := expandAvatar(
hook.Repo.URL,
fixMalformedAvatar(hook.Sender.Avatar),
)
author := hook.Sender.Login
if author == "" {
author = hook.Sender.Username
}
return &model.Build{
Event: model.EventTag,
Commit: hook.After,
Ref: fmt.Sprintf("refs/tags/%s", hook.Ref),
Link: fmt.Sprintf("%s/src/%s", hook.Repo.URL, hook.Ref),
Branch: fmt.Sprintf("refs/tags/%s", hook.Ref),
Message: fmt.Sprintf("created tag %s", hook.Ref),
Avatar: avatar,
Author: author,
Timestamp: time.Now().UTC().Unix(),
}
}
// helper function that extracts the Repository data from a Gogs push hook
func repoFromPush(hook *pushHook) *model.Repo {
fullName := fmt.Sprintf(
"%s/%s",
hook.Repo.Owner.Username,
hook.Repo.Name,
)
return &model.Repo{
Name: hook.Repo.Name,
Owner: hook.Repo.Owner.Username,
FullName: fullName,
FullName: hook.Repo.FullName,
Link: hook.Repo.URL,
}
}

View file

@ -27,6 +27,7 @@ func Test_parse(t *testing.T) {
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.Owner.Name).Equal("gordon")
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)
@ -37,6 +38,21 @@ func Test_parse(t *testing.T) {
g.Assert(hook.Sender.Avatar).Equal("http://gogs.golang.org///1.gravatar.com/avatar/8c58a0be77ee441bb8f8595b7f1b4e87")
})
g.It("Should parse tag hook payload", func() {
buf := bytes.NewBufferString(fixtures.HookPushTag)
hook, err := parsePush(buf)
g.Assert(err == nil).IsTrue()
g.Assert(hook.Ref).Equal("v1.0.0")
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.It("Should return a Build struct from a push hook", func() {
buf := bytes.NewBufferString(fixtures.HookPush)
hook, _ := parsePush(buf)

74
remote/gogs/parse.go Normal file
View file

@ -0,0 +1,74 @@
package gogs
import (
"io"
"net/http"
"github.com/drone/drone/model"
)
const (
hookEvent = "X-Gogs-Event"
hookPush = "push"
hookCreated = "create"
refBranch = "branch"
refTag = "tag"
)
// parseHook parses a Bitbucket hook from an http.Request request and returns
// Repo and Build detail. If a hook type is unsupported nil values are returned.
func parseHook(r *http.Request) (*model.Repo, *model.Build, error) {
switch r.Header.Get(hookEvent) {
case hookPush:
return parsePushHook(r.Body)
case hookCreated:
return parseCreatedHook(r.Body)
}
return nil, nil, nil
}
// parsePushHook parses a push hook and returns the Repo and Build details.
// If the commit type is unsupported nil values are returned.
func parsePushHook(payload io.Reader) (*model.Repo, *model.Build, error) {
var (
repo *model.Repo
build *model.Build
)
push, err := parsePush(payload)
if err != nil {
return nil, nil, err
}
// is this even needed?
if push.RefType == refBranch {
return nil, nil, nil
}
repo = repoFromPush(push)
build = buildFromPush(push)
return repo, build, err
}
// parseCreatedHook parses a push hook and returns the Repo and Build details.
// If the commit type is unsupported nil values are returned.
func parseCreatedHook(payload io.Reader) (*model.Repo, *model.Build, error) {
var (
repo *model.Repo
build *model.Build
)
push, err := parsePush(payload)
if err != nil {
return nil, nil, err
}
if push.RefType != refTag {
return nil, nil, nil
}
repo = repoFromPush(push)
build = buildFromTag(push)
return repo, build, err
}

View file

@ -0,0 +1 @@
package gogs

View file

@ -10,15 +10,17 @@ type pushHook struct {
Pusher struct {
Name string `json:"name"`
Email string `json:"email"`
Login string `json:"login"`
Username string `json:"username"`
} `json:"pusher"`
Repo struct {
ID int64 `json:"id"`
Name string `json:"name"`
URL string `json:"url"`
Private bool `json:"private"`
Owner 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 {
Name string `json:"name"`
Email string `json:"email"`
Username string `json:"username"`
@ -32,8 +34,9 @@ type pushHook struct {
} `json:"commits"`
Sender struct {
ID int64 `json:"id"`
Login string `json:"login"`
Avatar string `json:"avatar_url"`
ID int64 `json:"id"`
Login string `json:"login"`
Username string `json:"username"`
Avatar string `json:"avatar_url"`
} `json:"sender"`
}