From dcba48f91609ba81d44e8e2d6e45fe2c8ca3117c Mon Sep 17 00:00:00 2001 From: Michalis Zampetakis Date: Mon, 17 Jul 2023 22:30:06 +0300 Subject: [PATCH] Add bitbucket forge BranchHead implementation (#2011) In order to test this functionality, we had to expose the `BranchHead()` through an API endpoint ``` GET /repos/{repo_id}/branches/{branch}/head ``` The response is a string that contains the latest commit hash of the requested branch. --- server/forge/bitbucket/bitbucket.go | 5 ++- server/forge/bitbucket/internal/client.go | 40 +++++++++++++++-------- server/forge/bitbucket/internal/types.go | 8 +++++ 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/server/forge/bitbucket/bitbucket.go b/server/forge/bitbucket/bitbucket.go index 8f7dacf43..d06a24424 100644 --- a/server/forge/bitbucket/bitbucket.go +++ b/server/forge/bitbucket/bitbucket.go @@ -297,9 +297,8 @@ func (c *config) Branches(ctx context.Context, u *model.User, r *model.Repo, _ * } // BranchHead returns the sha of the head (latest commit) of the specified branch -func (c *config) BranchHead(_ context.Context, _ *model.User, _ *model.Repo, _ string) (string, error) { - // TODO(1138): missing implementation - return "", forge_types.ErrNotImplemented +func (c *config) BranchHead(ctx context.Context, u *model.User, r *model.Repo, branch string) (string, error) { + return c.newClient(ctx, u).GetBranchHead(r.Owner, r.Name, branch) } // PullRequests returns the pull requests of the named repository. diff --git a/server/forge/bitbucket/internal/client.go b/server/forge/bitbucket/internal/client.go index aca051805..0888f1f2c 100644 --- a/server/forge/bitbucket/internal/client.go +++ b/server/forge/bitbucket/internal/client.go @@ -34,19 +34,20 @@ const ( ) const ( - pathUser = "%s/2.0/user/" - pathEmails = "%s/2.0/user/emails" - pathPermissions = "%s/2.0/user/permissions/repositories?q=repository.full_name=%q" - pathWorkspace = "%s/2.0/workspaces/?%s" - pathRepo = "%s/2.0/repositories/%s/%s" - pathRepos = "%s/2.0/repositories/%s?%s" - pathHook = "%s/2.0/repositories/%s/%s/hooks/%s" - pathHooks = "%s/2.0/repositories/%s/%s/hooks?%s" - pathSource = "%s/2.0/repositories/%s/%s/src/%s/%s" - pathStatus = "%s/2.0/repositories/%s/%s/commit/%s/statuses/build" - pathBranches = "%s/2.0/repositories/%s/%s/refs/branches" - pathOrgPerms = "%s/2.0/workspaces/%s/permissions?%s" - pathPullRequests = "%s/2.0/repositories/%s/%s/pullrequests" + pathUser = "%s/2.0/user/" + pathEmails = "%s/2.0/user/emails" + pathPermissions = "%s/2.0/user/permissions/repositories?q=repository.full_name=%q" + pathWorkspace = "%s/2.0/workspaces/?%s" + pathRepo = "%s/2.0/repositories/%s/%s" + pathRepos = "%s/2.0/repositories/%s?%s" + pathHook = "%s/2.0/repositories/%s/%s/hooks/%s" + pathHooks = "%s/2.0/repositories/%s/%s/hooks?%s" + pathSource = "%s/2.0/repositories/%s/%s/src/%s/%s" + pathStatus = "%s/2.0/repositories/%s/%s/commit/%s/statuses/build" + pathBranches = "%s/2.0/repositories/%s/%s/refs/branches" + pathOrgPerms = "%s/2.0/workspaces/%s/permissions?%s" + pathPullRequests = "%s/2.0/repositories/%s/%s/pullrequests" + pathBranchCommits = "%s/2.0/repositories/%s/%s/commits/%s" ) type Client struct { @@ -183,6 +184,19 @@ func (c *Client) ListBranches(owner, name string) ([]*Branch, error) { return out.Values, err } +func (c *Client) GetBranchHead(owner, name, branch string) (string, error) { + out := new(CommitsResp) + uri := fmt.Sprintf(pathBranchCommits, c.base, owner, name, branch) + _, err := c.do(uri, get, nil, out) + if err != nil { + return "", err + } + if len(out.Values) == 0 { + return "", fmt.Errorf("no commits in branch %s", branch) + } + return out.Values[0].Hash, nil +} + func (c *Client) GetUserWorkspaceMembership(workspace, user string) (string, error) { out := new(WorkspaceMembershipResp) opts := &ListOpts{Page: 1, PageLen: 100} diff --git a/server/forge/bitbucket/internal/types.go b/server/forge/bitbucket/internal/types.go index 4c4889d7a..88a39874f 100644 --- a/server/forge/bitbucket/internal/types.go +++ b/server/forge/bitbucket/internal/types.go @@ -271,3 +271,11 @@ type PullRequest struct { ID uint `json:"id"` Title string `json:"title"` } + +type CommitsResp struct { + Values []*Commit `json:"values"` +} + +type Commit struct { + Hash string `json:"hash"` +}