Skip to content

Commit 8dd8542

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 afb202b commit 8dd8542

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
@@ -244,12 +244,13 @@ func TestGetCommitInfo(t *testing.T) {
244244
for _, tt := range tests {
245245
t.Run(tt.name, func(t *testing.T) {
246246
ctx, _ := rtesting.SetupFakeContext(t)
247+
observer, _ := zapobserver.New(zap.InfoLevel)
248+
fakelogger := zap.New(observer).Sugar()
247249
bbclient, mux, tearDown := bbcloudtest.SetupBBCloudClient(t)
248250
defer tearDown()
249-
v := &Provider{bbClient: bbclient}
250-
bbcloudtest.MuxCommits(t, mux, tt.event, []types.Commit{
251-
tt.commitinfo,
252-
})
251+
v := &Provider{Logger: fakelogger, bbClient: bbclient}
252+
bbcloudtest.MuxCommit(t, mux, tt.event, tt.commitinfo)
253+
bbcloudtest.MuxBranch(t, mux, tt.event, tt.commitinfo)
253254
bbcloudtest.MuxRepoInfo(t, mux, tt.event, tt.repoinfo)
254255

255256
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)