Skip to content

Commit

Permalink
feat: webhook events support for bitbucket server prebuild
Browse files Browse the repository at this point in the history
Signed-off-by: the-johnwick <[email protected]>
  • Loading branch information
the-johnwick committed Oct 3, 2024
1 parent 7525dbf commit e1b647f
Show file tree
Hide file tree
Showing 2 changed files with 137 additions and 0 deletions.
4 changes: 4 additions & 0 deletions cmd/daytona/config/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ func GetPrebuildScopesFromGitProviderId(providerId string) string {
return "admin:repo_hook"
case "bitbucket":
return "webhooks"
case "bitbucket-server":
return "webhooks"
case "azure-devops":
return "Work (Read, Write & Manage); Build (Read & Execute)"
default:
Expand All @@ -143,6 +145,8 @@ func GetWebhookEventHeaderKeyFromGitProvider(providerId string) string {
return "X-Gitlab-Event"
case "bitbucket":
return "X-Event-Key"
case "bitbucket-server":
return "X-Event-Key"
case "gitea":
return "X-Gitea-Event"
case "azure-devops":
Expand Down
133 changes: 133 additions & 0 deletions pkg/gitprovider/bitbucketserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ import (
"net/http"
"net/url"

"github.com/daytonaio/daytona/internal/util"
bitbucketv1 "github.com/gfleury/go-bitbucket-v1"
bitbucketServerWebhook "github.com/go-playground/webhooks/v6/bitbucket-server"
"github.com/mitchellh/mapstructure"
)

Expand Down Expand Up @@ -524,3 +526,134 @@ func (b *BitbucketServerGitProvider) FormatError(statusCode int, message string)

return fmt.Errorf("status code: %d err: Request failed with %s", statusCode, message)
}

func (b *BitbucketServerGitProvider) GetPrebuildWebhook(repo *GitRepository, endpointUrl string) (*string, error) {
client, err := b.getApiClient()
if err != nil {
return nil, err
}

hooks, err := client.DefaultApi.FindWebhooks(repo.Owner, repo.Id, nil)
if err != nil {
return nil, b.FormatError(hooks.StatusCode, hooks.Message)
}

if len(hooks.Values) == 0 {
return nil, nil
}

hookList, err := bitbucketv1.GetWebhooksResponse(hooks)
if err != nil {
return nil, err
}

for _, hook := range hookList {
if hook.Url == endpointUrl {
return util.Pointer(strconv.Itoa(int(hook.ID))), nil
}
}

return nil, nil
}

func (b *BitbucketServerGitProvider) UnregisterPrebuildWebhook(repo *GitRepository, id string) error {
client, err := b.getApiClient()
if err != nil {
return err
}

idInt, err := strconv.Atoi(id)
if err != nil {
return fmt.Errorf("invalid webhook ID: %v", err)
}

response, err := client.DefaultApi.DeleteWebhook(repo.Owner, repo.Id, int32(idInt))
if err != nil {
return b.FormatError(response.StatusCode, response.Message)
}

return nil
}

func (b *BitbucketServerGitProvider) RegisterPrebuildWebhook(repo *GitRepository, endpointUrl string) (string, error) {
client, err := b.getApiClient()
if err != nil {
return "", err
}

hook, err := client.DefaultApi.CreateWebhook(repo.Owner, repo.Id, &bitbucketv1.Webhook{
Active: true,
Events: []string{"repo:push"},
Url: endpointUrl,
}, []string{"repo:push"})
if err != nil {
return "", b.FormatError(hook.StatusCode, hook.Message)
}

webhook, err := bitbucketv1.GetWebhooksResponse(hook)
if err != nil {
return "", err
}

return strconv.Itoa(webhook[0].ID), nil

}

func (b *BitbucketServerGitProvider) GetCommitsRange(repo *GitRepository, initialSha string, currentSha string) (int, error) {
client, err := b.getApiClient()
if err != nil {
return 0, err
}

commits, err := client.DefaultApi.GetCommits(repo.Owner, repo.Id, map[string]interface{}{
"since": initialSha,
"until": currentSha,
})
if err != nil {
return 0, b.FormatError(commits.StatusCode, commits.Message)
}

commitsResponse, err := bitbucketv1.GetCommitsResponse(commits)
if err != nil {
return 0, err
}

return len(commitsResponse), nil
}

func (b *BitbucketServerGitProvider) ParseEventData(request *http.Request) (*GitEventData, error) {
if request.Header.Get("X-Event-Key") != "repo:refs_changed" {
return nil, errors.New("invalid event key")
}
hook, err := bitbucketServerWebhook.New()
if err != nil {
return nil, err
}

event, err := hook.Parse(request, bitbucketServerWebhook.RepositoryReferenceChangedEvent)
if err != nil {
return nil, err
}

pushEvent, ok := event.(*bitbucketServerWebhook.RepositoryReferenceChangedPayload)
if !ok {
return nil, errors.New("invalid event payload")
}

if len(pushEvent.Changes) == 0 {
return nil, errors.New("no changes in the push event")
}

gitEventData := &GitEventData{
Url: fmt.Sprintf("%s/scm/%s/%s.git", b.baseApiUrl, pushEvent.Repository.Project.Key, pushEvent.Repository.Slug),
Owner: pushEvent.Repository.Project.Key,
Branch: pushEvent.Changes[0].Reference.DisplayID,
Sha: pushEvent.Changes[0].ToHash,
}

for _, change := range pushEvent.Changes {
gitEventData.AffectedFiles = append(gitEventData.AffectedFiles, change.ToHash)
}

return gitEventData, nil
}

0 comments on commit e1b647f

Please sign in to comment.