Skip to content

Commit

Permalink
add bitbucket v5.4 support
Browse files Browse the repository at this point in the history
  • Loading branch information
bparees committed Oct 17, 2017
1 parent 572fb85 commit 5cfb55e
Show file tree
Hide file tree
Showing 5 changed files with 375 additions and 109 deletions.
131 changes: 90 additions & 41 deletions pkg/build/webhook/bitbucket/bitbucket.go
Expand Up @@ -3,6 +3,7 @@ package bitbucket
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
"mime"
"net/http"
Expand All @@ -28,13 +29,7 @@ func New() *WebHook {
// More information on Bitbucket push events here:
// https://confluence.atlassian.com/bitbucket/event-payloads-740262817.html#EventPayloads-Push
type pushEvent struct {
Actor user `json:"actor"`
Push push `json:"push"`
}

type user struct {
Username string `json:"username"`
DisplayName string `json:"display_name"`
Push push `json:"push"`
}

type push struct {
Expand All @@ -43,8 +38,7 @@ type push struct {

type change struct {
Commits []commit `json:"commits"`
New new `json:"new"`
Old old `json:"old"`
Old info `json:"old"`
}

type commit struct {
Expand All @@ -53,16 +47,29 @@ type commit struct {
Author user `json:"author"`
}

type new struct {
Type string `json:"type"`
Name string `json:"name"`
type user struct {
Username string `json:"username"`
DisplayName string `json:"display_name"`
}

type old struct {
type info struct {
Type string `json:"type"`
Name string `json:"name"`
}

type pushEvent54 struct {
Changes []change54 `json:"changes"`
}

type change54 struct {
Ref ref `json:"ref"`
ToHash string `json:"toHash"`
}

type ref struct {
DisplayID string `json:"displayId"`
}

// Extract services webhooks from bitbucket.com
func (p *WebHook) Extract(buildCfg *buildapi.BuildConfig, secret, path string, req *http.Request) (revision *buildapi.SourceRevision, envvars []kapi.EnvVar, dockerStrategyOptions *buildapi.DockerStrategyOptions, proceed bool, err error) {
triggers, err := webhook.FindTriggerPolicy(buildapi.BitbucketWebHookBuildTriggerType, buildCfg)
Expand All @@ -81,40 +88,30 @@ func (p *WebHook) Extract(buildCfg *buildapi.BuildConfig, secret, path string, r
}

method := getEvent(req.Header)
if method != "repo:push" {
branch := ""
switch method {
// https://confluence.atlassian.com/bitbucket/event-payloads-740262817.html
case "repo:push":
branch, revision, err = getInfoFromEvent(req.Body)
if err != nil {
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(err.Error())
}

// https://confluence.atlassian.com/bitbucketserver/event-payload-938025882.html
case "repo:refs_changed":
branch, revision, err = getInfoFromEvent54(req.Body)
if err != nil {
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(err.Error())
}
default:
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(fmt.Sprintf("Unknown Bitbucket X-Event-Key %s", method))
}

body, err := ioutil.ReadAll(req.Body)
if err != nil {
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(err.Error())
}

var event pushEvent
if err = json.Unmarshal(body, &event); err != nil {
return revision, envvars, dockerStrategyOptions, false, errors.NewBadRequest(err.Error())
}

// We use old here specifically. If the branch is deleted in a push, the New
// object will be nil.
if !webhook.GitRefMatches(event.Push.Changes[0].Old.Name, webhook.DefaultConfigRef, &buildCfg.Spec.Source) {
glog.V(2).Infof("Skipping build for BuildConfig %s/%s. Branch reference from '%s' does not match configuration", buildCfg.Namespace, buildCfg, event)
if !webhook.GitRefMatches(branch, webhook.DefaultConfigRef, &buildCfg.Spec.Source) {
glog.V(2).Infof("Skipping build for BuildConfig %s/%s. Branch reference '%s' does not match configuration", buildCfg.Namespace, buildCfg, branch)
return revision, envvars, dockerStrategyOptions, false, err
}

lastCommit := event.Push.Changes[0].Commits[0]
author := buildapi.SourceControlUser{
Name: lastCommit.Author.Username,
}

revision = &buildapi.SourceRevision{
Git: &buildapi.GitSourceRevision{
Commit: lastCommit.Hash,
Author: author,
Committer: author,
Message: lastCommit.Message,
},
}
return revision, envvars, dockerStrategyOptions, true, err
}

Expand All @@ -139,3 +136,55 @@ func verifyRequest(req *http.Request) error {
func getEvent(header http.Header) string {
return header.Get("X-Event-Key")
}

func getInfoFromEvent(body io.ReadCloser) (string, *buildapi.SourceRevision, error) {
data, err := ioutil.ReadAll(body)
if err != nil {
return "", nil, err
}

var event pushEvent
if err = json.Unmarshal(data, &event); err != nil {
return "", nil, err
}
if len(event.Push.Changes) == 0 {
return "", nil, fmt.Errorf("Unable to extract valid event from payload: %s", string(data))
}
lastCommit := event.Push.Changes[0].Commits[0]
author := buildapi.SourceControlUser{
Name: lastCommit.Author.Username,
}

revision := &buildapi.SourceRevision{
Git: &buildapi.GitSourceRevision{
Commit: lastCommit.Hash,
Author: author,
Committer: author,
Message: lastCommit.Message,
},
}
// We use old here specifically. If the branch is deleted in a push, the New
// object will be nil.
return event.Push.Changes[0].Old.Name, revision, nil
}

func getInfoFromEvent54(body io.ReadCloser) (string, *buildapi.SourceRevision, error) {
data, err := ioutil.ReadAll(body)
if err != nil {
return "", nil, err
}

var event pushEvent54
if err = json.Unmarshal(data, &event); err != nil {
return "", nil, err
}
if len(event.Changes) == 0 {
return "", nil, fmt.Errorf("Unable to extract valid event from payload: %s", string(data))
}
revision := &buildapi.SourceRevision{
Git: &buildapi.GitSourceRevision{
Commit: event.Changes[0].ToHash,
},
}
return event.Changes[0].Ref.DisplayID, revision, nil
}

0 comments on commit 5cfb55e

Please sign in to comment.