Skip to content

Commit 02cb1b7

Browse files
zakiskchmouel
authored andcommitted
fix(bitbucketcloud): optimize commit info fetch
Replace paginated GetCommits API with direct GetCommit lookup to eliminate performance bottleneck on repositories with many commits. When SHA is unavailable, fetch branch info first to get HEAD commit SHA, then use GetCommit for single-commit retrieval. This reduces webhook processing time from 49 seconds to <1 second on repositories with 2333+ commits by avoiding pagination through entire commit history. Fixes: #2336 https://issues.redhat.com/browse/SRVKP-10617 Signed-off-by: Zaki Shaikh <zashaikh@redhat.com> Assisted-by: Claude Sonnet 4.5 (via Claude Code)
1 parent 7427b70 commit 02cb1b7

3 files changed

Lines changed: 72 additions & 25 deletions

File tree

pkg/provider/bitbucketcloud/bitbucket.go

Lines changed: 29 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -217,31 +217,44 @@ func (v *Provider) SetClient(_ context.Context, run *params.Run, event *info.Eve
217217
}
218218

219219
func (v *Provider) GetCommitInfo(_ context.Context, event *info.Event) error {
220-
branchortag := event.SHA
221-
if branchortag == "" {
222-
branchortag = event.HeadBranch
220+
// If we don't have a SHA, get it from the branch first
221+
sha := event.SHA
222+
if sha == "" && event.HeadBranch != "" {
223+
v.Logger.Infof("fetching branch info to get commit SHA for branch: %s", event.HeadBranch)
224+
branchInfo, err := v.Client().Repositories.Repository.GetBranch(&bitbucket.RepositoryBranchOptions{
225+
Owner: event.Organization,
226+
RepoSlug: event.Repository,
227+
BranchName: event.HeadBranch,
228+
})
229+
if err != nil {
230+
return err
231+
}
232+
// Extract hash from Target map
233+
if hash, ok := branchInfo.Target["hash"].(string); ok {
234+
sha = hash
235+
} else {
236+
return fmt.Errorf("cannot extract commit hash from branch %s", event.HeadBranch)
237+
}
223238
}
224-
response, err := v.Client().Repositories.Commits.GetCommits(&bitbucket.CommitsOptions{
225-
Owner: event.Organization,
226-
RepoSlug: event.Repository,
227-
Branchortag: branchortag,
239+
240+
// Use GetCommit API for direct single-commit fetch (no pagination)
241+
v.Logger.Infof("fetching commit info using GetCommit API for SHA: %s", sha)
242+
response, err := v.Client().Repositories.Commits.GetCommit(&bitbucket.CommitsOptions{
243+
Owner: event.Organization,
244+
RepoSlug: event.Repository,
245+
Revision: sha,
228246
})
229247
if err != nil {
230248
return err
231249
}
250+
232251
commitMap, ok := response.(map[string]any)
233252
if !ok {
234-
return fmt.Errorf("cannot convert")
235-
}
236-
values, ok := commitMap["values"].([]any)
237-
if !ok {
238-
return fmt.Errorf("cannot convert")
239-
}
240-
if len(values) == 0 {
241-
return fmt.Errorf("we did not get commit information from commit: %s", event.SHA)
253+
return fmt.Errorf("cannot convert commit response")
242254
}
255+
243256
commitinfo := &types.Commit{}
244-
err = mapstructure.Decode(values[0], commitinfo)
257+
err = mapstructure.Decode(commitMap, commitinfo)
245258
if err != nil {
246259
return err
247260
}

pkg/provider/bitbucketcloud/bitbucket_test.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,12 +225,13 @@ func TestGetCommitInfo(t *testing.T) {
225225
for _, tt := range tests {
226226
t.Run(tt.name, func(t *testing.T) {
227227
ctx, _ := rtesting.SetupFakeContext(t)
228+
observer, _ := zapobserver.New(zap.InfoLevel)
229+
fakelogger := zap.New(observer).Sugar()
228230
bbclient, mux, tearDown := bbcloudtest.SetupBBCloudClient(t)
229231
defer tearDown()
230-
v := &Provider{bbClient: bbclient}
231-
bbcloudtest.MuxCommits(t, mux, tt.event, []types.Commit{
232-
tt.commitinfo,
233-
})
232+
v := &Provider{Logger: fakelogger, bbClient: bbclient}
233+
bbcloudtest.MuxCommit(t, mux, tt.event, tt.commitinfo)
234+
bbcloudtest.MuxBranch(t, mux, tt.event, tt.commitinfo)
234235
bbcloudtest.MuxRepoInfo(t, mux, tt.event, tt.repoinfo)
235236

236237
if err := v.GetCommitInfo(ctx, tt.event); (err != nil) != tt.wantErr {

pkg/provider/bitbucketcloud/test/bbcloudtest.go

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -121,15 +121,48 @@ func MuxListDirFiles(t *testing.T, mux *http.ServeMux, event *info.Event, dirs m
121121
}
122122
}
123123

124-
func MuxCommits(t *testing.T, mux *http.ServeMux, event *info.Event, commits []types.Commit) {
124+
// MuxCommit mocks the GetCommit API (single commit, not paginated).
125+
func MuxCommit(t *testing.T, mux *http.ServeMux, event *info.Event, commit types.Commit) {
125126
t.Helper()
126127

127-
path := fmt.Sprintf("/repositories/%s/%s/commits/%s", event.Organization, event.Repository, event.SHA)
128+
shas := []string{}
129+
if event.SHA != "" {
130+
shas = append(shas, event.SHA)
131+
}
132+
if commit.Hash != "" && commit.Hash != event.SHA {
133+
shas = append(shas, commit.Hash)
134+
}
135+
if len(shas) == 0 {
136+
shas = append(shas, "HEAD")
137+
}
138+
139+
for _, sha := range shas {
140+
path := fmt.Sprintf("/repositories/%s/%s/commit/%s", event.Organization, event.Repository, sha)
141+
mux.HandleFunc(path, func(rw http.ResponseWriter, _ *http.Request) {
142+
// GetCommit returns a single commit object, not {values: [...]}
143+
b, _ := json.Marshal(commit)
144+
fmt.Fprint(rw, string(b))
145+
})
146+
}
147+
}
148+
149+
func MuxBranch(t *testing.T, mux *http.ServeMux, event *info.Event, commit types.Commit) {
150+
t.Helper()
151+
152+
if event.HeadBranch == "" {
153+
return
154+
}
155+
156+
path := fmt.Sprintf("/repositories/%s/%s/refs/branches/%s", event.Organization, event.Repository, event.HeadBranch)
128157
mux.HandleFunc(path, func(rw http.ResponseWriter, _ *http.Request) {
129-
dircontents := map[string][]types.Commit{
130-
"values": commits,
158+
// Return the commit hash that this branch points to
159+
branch := map[string]interface{}{
160+
"name": event.HeadBranch,
161+
"target": map[string]interface{}{
162+
"hash": commit.Hash,
163+
},
131164
}
132-
b, _ := json.Marshal(dircontents)
165+
b, _ := json.Marshal(branch)
133166
fmt.Fprint(rw, string(b))
134167
})
135168
}

0 commit comments

Comments
 (0)