diff --git a/go.mod b/go.mod index d4ff959f2a1..262c9fb5f5b 100644 --- a/go.mod +++ b/go.mod @@ -43,7 +43,7 @@ require ( github.com/migueleliasweb/go-github-mock v1.5.0 github.com/moby/term v0.5.2 github.com/muesli/termenv v0.16.0 - github.com/neticdk/go-bitbucket v1.0.4 + github.com/neticdk/go-bitbucket v1.0.5 github.com/oklog/ulid/v2 v2.1.1 github.com/prometheus/client_golang v1.23.2 github.com/rs/zerolog v1.34.0 diff --git a/go.sum b/go.sum index af28cb6907e..b7589fb928f 100644 --- a/go.sum +++ b/go.sum @@ -451,8 +451,8 @@ github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/neticdk/go-bitbucket v1.0.4 h1:Nl7LtB+YuMSIupJ4m2RH7AG50yEJm9HeheqnZRWxy7A= -github.com/neticdk/go-bitbucket v1.0.4/go.mod h1:4ZMxzmr5hi/EoLdydtR7h4dd4DpqK8tbnVLbAkscRc8= +github.com/neticdk/go-bitbucket v1.0.5 h1:H/++KM+O0EXVDbgMadbAsKwqjLKi0vDwa+vGU9lMChg= +github.com/neticdk/go-bitbucket v1.0.5/go.mod h1:4ZMxzmr5hi/EoLdydtR7h4dd4DpqK8tbnVLbAkscRc8= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= diff --git a/server/forge/bitbucketdatacenter/bitbucketdatacenter.go b/server/forge/bitbucketdatacenter/bitbucketdatacenter.go index 063534e1aca..80b717e487d 100644 --- a/server/forge/bitbucketdatacenter/bitbucketdatacenter.go +++ b/server/forge/bitbucketdatacenter/bitbucketdatacenter.go @@ -499,7 +499,7 @@ func (c *client) Deactivate(ctx context.Context, u *model.User, r *model.Repo, l } func (c *client) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model.Pipeline, error) { - hook, err := parseHook(r, c.url) + hook, currCommit, prevCommit, err := parseHook(r, c.url) if err != nil { return nil, nil, fmt.Errorf("unable to parse hook: %w", err) } @@ -518,7 +518,7 @@ func (c *client) Hook(ctx context.Context, r *http.Request) (*model.Repo, *model switch e := hook.Event.(type) { case *bb.RepositoryPushEvent: - pipe, err = c.updatePipelineFromCommit(ctx, user, repo, hook.Pipeline) + pipe, err = c.updatePipelineFromCommits(ctx, user, repo, hook.Pipeline, currCommit, prevCommit) case *bb.PullRequestEvent: pipe, err = c.updatePipelineFromPullRequest(ctx, user, repo, hook.Pipeline, e.PullRequest.ID) } @@ -558,7 +558,7 @@ func (c *client) getUserAndRepo(ctx context.Context, r *model.Repo) (*model.User return user, repo, nil } -func (c *client) updatePipelineFromCommit(ctx context.Context, u *model.User, r *model.Repo, p *model.Pipeline) (*model.Pipeline, error) { +func (c *client) updatePipelineFromCommits(ctx context.Context, u *model.User, r *model.Repo, p *model.Pipeline, currCommit, prevCommit string) (*model.Pipeline, error) { if p == nil { return nil, nil } @@ -574,9 +574,15 @@ func (c *client) updatePipelineFromCommit(ctx context.Context, u *model.User, r } p.Message = commit.Message - opts := &bb.ListOptions{} + opts := &bb.CompareChangesOptions{} + if currCommit != "" { + opts.From = currCommit + } + if prevCommit != "" { + opts.To = prevCommit + } for { - changes, resp, err := bc.Projects.ListChanges(ctx, r.Owner, r.Name, p.Commit, opts) + changes, resp, err := bc.Projects.CompareChanges(ctx, r.Owner, r.Name, opts) if err != nil { return nil, fmt.Errorf("unable to list commit changes: %w", err) } diff --git a/server/forge/bitbucketdatacenter/convert.go b/server/forge/bitbucketdatacenter/convert.go index 9eb5fcee333..79c5a1d370f 100644 --- a/server/forge/bitbucketdatacenter/convert.go +++ b/server/forge/bitbucketdatacenter/convert.go @@ -109,6 +109,19 @@ func convertRepositoryPushEvent(ev *bb.RepositoryPushEvent, baseURL string) *mod return pipeline } +func convertGetCommitRange(ev *bb.RepositoryPushEvent) (currCommit, prevCommit string) { + if len(ev.Changes) == 0 { + return "", "" + } + change := ev.Changes[0] + if change.FromHash == "0000000000000000000000000000000000000000" { + return change.ToHash, "" + } else if change.ToHash == "0000000000000000000000000000000000000000" { + return "", change.FromHash + } + return change.ToHash, change.FromHash +} + func convertPullRequestEvent(ev *bb.PullRequestEvent, baseURL string) *model.Pipeline { pipeline := &model.Pipeline{ Commit: ev.PullRequest.Source.Latest, diff --git a/server/forge/bitbucketdatacenter/parse.go b/server/forge/bitbucketdatacenter/parse.go index 75622e0db85..b24fb00ecd8 100644 --- a/server/forge/bitbucketdatacenter/parse.go +++ b/server/forge/bitbucketdatacenter/parse.go @@ -17,10 +17,10 @@ type HookResult struct { Payload []byte } -func parseHook(r *http.Request, baseURL string) (*HookResult, error) { +func parseHook(r *http.Request, baseURL string) (*HookResult, string, string, error) { ev, payload, err := bb.ParsePayloadWithoutSignature(r) if err != nil { - return nil, fmt.Errorf("unable to parse payload from webhook invocation: %w", err) + return nil, "", "", fmt.Errorf("unable to parse payload from webhook invocation: %w", err) } result := &HookResult{ @@ -32,12 +32,13 @@ func parseHook(r *http.Request, baseURL string) (*HookResult, error) { case *bb.RepositoryPushEvent: result.Repo = convertRepo(&e.Repository, nil, "") result.Pipeline = convertRepositoryPushEvent(e, baseURL) + currCommit, prevCommit := convertGetCommitRange(e) + return result, currCommit, prevCommit, nil case *bb.PullRequestEvent: result.Repo = convertRepo(&e.PullRequest.Target.Repository, nil, "") result.Pipeline = convertPullRequestEvent(e, baseURL) + return result, "", "", nil default: - return nil, &types.ErrIgnoreEvent{Event: fmt.Sprintf("%T", e), Reason: "unsupported webhook event type"} + return nil, "", "", &types.ErrIgnoreEvent{Event: fmt.Sprintf("%T", e), Reason: "unsupported webhook event type"} } - - return result, nil } diff --git a/server/forge/bitbucketdatacenter/parse_test.go b/server/forge/bitbucketdatacenter/parse_test.go index 30549b2c19d..628e0d51808 100644 --- a/server/forge/bitbucketdatacenter/parse_test.go +++ b/server/forge/bitbucketdatacenter/parse_test.go @@ -20,10 +20,12 @@ func Test_parseHook(t *testing.T) { req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Event-Key", "pr:opened") - result, err := parseHook(req, "https://bitbucket.example.com") + result, curCommit, prevCommit, err := parseHook(req, "https://bitbucket.example.com") assert.NoError(t, err) assert.NotNil(t, result) + assert.Empty(t, curCommit) + assert.Empty(t, prevCommit) assert.IsType(t, &bb.PullRequestEvent{}, result.Event) assert.NotNil(t, result.Repo) assert.NotNil(t, result.Pipeline) @@ -40,10 +42,12 @@ func Test_parseHook(t *testing.T) { req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Event-Key", "pr:opened") - result, err := parseHook(req, "https://bitbucket.example.com") + result, curCommit, prevCommit, err := parseHook(req, "https://bitbucket.example.com") assert.NoError(t, err) assert.NotNil(t, result) + assert.Empty(t, curCommit) + assert.Empty(t, prevCommit) assert.IsType(t, &bb.PullRequestEvent{}, result.Event) assert.NotNil(t, result.Repo) assert.NotNil(t, result.Pipeline) @@ -60,7 +64,7 @@ func Test_parseHook(t *testing.T) { req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Event-Key", "repo:refs_changed") - result, err := parseHook(req, "https://bitbucket.example.com") + result, curCommit, prevCommit, err := parseHook(req, "https://bitbucket.example.com") assert.NoError(t, err) assert.NotNil(t, result) @@ -68,6 +72,8 @@ func Test_parseHook(t *testing.T) { assert.NotNil(t, result.Repo) assert.NotNil(t, result.Pipeline) assert.NotNil(t, result.Payload) + assert.Equal(t, curCommit, "76797d54bca87db6d1e3e82ee40622c7908aa514") + assert.Equal(t, prevCommit, "e0e15221b987fd8296141c0faa6a79f7c86ca4ce") assert.Equal(t, "DEV/deployment-automation", result.Repo.FullName) assert.Equal(t, "76797d54bca87db6d1e3e82ee40622c7908aa514", result.Pipeline.Commit) assert.Equal(t, model.EventPush, result.Pipeline.Event) @@ -80,10 +86,12 @@ func Test_parseHook(t *testing.T) { req.Header.Set("Content-Type", "application/json") req.Header.Set("X-Event-Key", "pr:merged") - result, err := parseHook(req, "https://bitbucket.example.com") + result, curCommit, prevCommit, err := parseHook(req, "https://bitbucket.example.com") assert.NoError(t, err) assert.NotNil(t, result) + assert.Empty(t, curCommit) + assert.Empty(t, prevCommit) assert.IsType(t, &bb.PullRequestEvent{}, result.Event) assert.NotNil(t, result.Repo) assert.NotNil(t, result.Pipeline)