github.com/sharovik/devbot@v1.0.1-0.20240308094637-4a0387c40516/internal/client/bitbucket.go (about)

     1  package client
     2  
     3  import (
     4  	"encoding/json"
     5  	"errors"
     6  	"fmt"
     7  	"net/http"
     8  	"net/url"
     9  	"time"
    10  
    11  	_time "github.com/sharovik/devbot/internal/service/time"
    12  
    13  	"github.com/sharovik/devbot/internal/dto"
    14  	"github.com/sharovik/devbot/internal/log"
    15  )
    16  
    17  // BitBucketClient the bitbucket client struct
    18  type BitBucketClient struct {
    19  	client           BaseHTTPClientInterface
    20  	OauthToken       string
    21  	OauthTokenExpire time.Time
    22  	RefreshToken     string
    23  }
    24  
    25  type responseAccessToken struct {
    26  	AccessToken  string `json:"access_token"`
    27  	Scopes       string `json:"scopes"`
    28  	ExpiresIn    int    `json:"expires_in"`
    29  	RefreshToken string `json:"refresh_token"`
    30  	TokenType    string `json:"token_type"`
    31  }
    32  
    33  const (
    34  	//DefaultBitBucketBaseAPIUrl the base url
    35  	DefaultBitBucketBaseAPIUrl = "https://api.bitbucket.org/2.0"
    36  
    37  	//DefaultBitBucketAccessTokenURL the access token endpoint which will be used for token generation
    38  	DefaultBitBucketAccessTokenURL = "https://bitbucket.org/site/oauth2"
    39  
    40  	//DefaultBitBucketMainBranch the default main branch
    41  	DefaultBitBucketMainBranch = "master"
    42  
    43  	//ErrorBranchExists error message for "branch exists error"
    44  	ErrorBranchExists = "BRANCH_ALREADY_EXISTS"
    45  
    46  	//StrategySquash the squash strategy which can be used during the merge
    47  	StrategySquash = "squash"
    48  
    49  	//StrategyMerge the default merge strategy which can be used during the merge
    50  	StrategyMerge = "merge_commit"
    51  
    52  	//ErrorMsgNoAccess error message response of bot, once he got a bad status code from the API
    53  	ErrorMsgNoAccess = "received unauthorized response. Looks like I'm not permitted to do any actions to that repository"
    54  )
    55  
    56  // Init initialise the client
    57  func (b *BitBucketClient) Init(client BaseHTTPClientInterface) {
    58  	b.client = client
    59  }
    60  
    61  func (b *BitBucketClient) isTokenInvalid() bool {
    62  	if b.OauthToken == "" {
    63  		log.Logger().Warn().Str("error", "oauth_empty").Msg("Invalid token")
    64  		return true
    65  	}
    66  
    67  	if b.OauthTokenExpire.Unix() <= _time.Service.Now().Unix() {
    68  		log.Logger().Warn().Time("time", b.OauthTokenExpire).Str("error", "expired").Msg("Invalid token")
    69  		return true
    70  	}
    71  
    72  	return false
    73  }
    74  
    75  func (b *BitBucketClient) beforeRequest() error {
    76  	log.Logger().StartMessage("Before BitBucket request")
    77  	if b.isTokenInvalid() {
    78  		log.Logger().Warn().Msg("Trying to regenerate the token")
    79  		if err := b.loadAuthToken(); err != nil {
    80  			log.Logger().AddError(err).Msg("Failed to generate new token")
    81  			log.Logger().FinishMessage("Before BitBucket request")
    82  			return err
    83  		}
    84  	}
    85  
    86  	log.Logger().FinishMessage("Before BitBucket request")
    87  	return nil
    88  }
    89  
    90  // GetAuthToken method retrieves the access token which can be used for custom needs outside of the internal services
    91  func (b *BitBucketClient) GetAuthToken() (string, error) {
    92  	if err := b.beforeRequest(); err != nil {
    93  		log.Logger().FinishMessage("Can't load access token")
    94  		return "", err
    95  	}
    96  
    97  	return b.OauthToken, nil
    98  }
    99  
   100  func (b *BitBucketClient) loadAuthToken() error {
   101  	log.Logger().StartMessage("Loading OAuth token")
   102  
   103  	b.client.SetBaseURL(DefaultBitBucketAccessTokenURL)
   104  	b.client.SetOauthToken("") //this will cleanup the token in the client and will generate new basic auth for specific client_id and client_secret
   105  
   106  	formData := url.Values{}
   107  	formData.Add("grant_type", "client_credentials")
   108  
   109  	response, _, err := b.client.Post("/access_token", formData.Encode(), map[string]string{
   110  		"Content-Type": "application/x-www-form-urlencoded;",
   111  		"Authorization": fmt.Sprintf("Basic %s", b.client.BasicAuth(
   112  			b.client.GetClientID(),
   113  			b.client.GetClientSecret(),
   114  		)),
   115  	})
   116  	if err != nil {
   117  		return err
   118  	}
   119  
   120  	var responseObject responseAccessToken
   121  	err = json.Unmarshal(response, &responseObject)
   122  	if err != nil {
   123  		return err
   124  	}
   125  
   126  	b.RefreshToken = responseObject.RefreshToken
   127  	b.OauthTokenExpire = _time.Service.Now().Add(time.Second * time.Duration(responseObject.ExpiresIn))
   128  	b.OauthToken = responseObject.AccessToken
   129  	b.client.SetOauthToken(responseObject.AccessToken)
   130  
   131  	log.Logger().FinishMessage("Loading OAuth token")
   132  	return nil
   133  }
   134  
   135  // CreateBranch creates the branch in API
   136  func (b *BitBucketClient) CreateBranch(workspace string, repositorySlug string, branchName string) (dto.BitBucketResponseBranchCreate, error) {
   137  	log.Logger().StartMessage("Create branch")
   138  	if err := b.beforeRequest(); err != nil {
   139  		log.Logger().FinishMessage("Create branch")
   140  		return dto.BitBucketResponseBranchCreate{}, err
   141  	}
   142  
   143  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   144  
   145  	endpoint := fmt.Sprintf("/repositories/%s/%s/refs/branches/%s", workspace, repositorySlug, branchName)
   146  	response, statusCode, err := b.client.Get(endpoint, map[string]string{})
   147  	if err != nil {
   148  		log.Logger().FinishMessage("Create branch")
   149  		return dto.BitBucketResponseBranchCreate{}, err
   150  	}
   151  
   152  	responseObject := dto.BitBucketResponseBranchCreate{}
   153  	if statusCode == http.StatusNotFound {
   154  		log.Logger().Info().Str("branch", branchName).Msg("Release branch wasn't found. Trying to create it.")
   155  		request := dto.BitBucketRequestBranchCreate{
   156  			Name: branchName,
   157  			Target: dto.BitBucketBranchTarget{
   158  				Hash: DefaultBitBucketMainBranch,
   159  			},
   160  		}
   161  
   162  		byteRequest, err := json.Marshal(request)
   163  		if err != nil {
   164  			log.Logger().FinishMessage("Create branch")
   165  			return dto.BitBucketResponseBranchCreate{}, err
   166  		}
   167  
   168  		endpoint := fmt.Sprintf("/repositories/%s/%s/refs/branches", workspace, repositorySlug)
   169  		response, statusCode, err := b.client.Post(endpoint, byteRequest, map[string]string{})
   170  		if err != nil {
   171  			log.Logger().AddError(err).
   172  				Msg("Failed to trigger request")
   173  			log.Logger().FinishMessage("Create branch")
   174  
   175  			return dto.BitBucketResponseBranchCreate{}, err
   176  		}
   177  
   178  		if err := json.Unmarshal(response, &responseObject); err != nil {
   179  			log.Logger().Info().
   180  				Str("branch", branchName).
   181  				Int("status_code", statusCode).
   182  				Str("response", string(response)).
   183  				Msg("Failed to unmarshal response")
   184  			log.Logger().FinishMessage("Create branch")
   185  			return dto.BitBucketResponseBranchCreate{}, err
   186  		}
   187  
   188  		if statusCode == http.StatusBadRequest {
   189  			if responseObject.Data.Key == ErrorBranchExists {
   190  				log.Logger().Info().
   191  					Str("branch", branchName).
   192  					Int("status_code", statusCode).
   193  					RawJSON("response", response).
   194  					Msg("Branch already exists")
   195  				log.Logger().FinishMessage("Create branch")
   196  				return responseObject, nil
   197  			}
   198  		}
   199  
   200  		if statusCode != http.StatusCreated {
   201  			log.Logger().Warn().
   202  				Str("branch", branchName).
   203  				Int("status_code", statusCode).
   204  				Interface("response", responseObject).
   205  				Msg("Bad status code received")
   206  
   207  			log.Logger().FinishMessage("Create branch")
   208  			return dto.BitBucketResponseBranchCreate{}, errors.New("wrong status code received during the branch creation. See the logs for more information. ")
   209  		}
   210  
   211  		log.Logger().Info().
   212  			Str("branch", branchName).
   213  			Int("status_code", statusCode).
   214  			RawJSON("response", response).Msg("Create branch result")
   215  		log.Logger().FinishMessage("Create branch")
   216  		return responseObject, nil
   217  	}
   218  
   219  	err = json.Unmarshal(response, &responseObject)
   220  	if err != nil {
   221  		log.Logger().AddError(err).Msg("Error during response unmarshal")
   222  		log.Logger().FinishMessage("Create branch")
   223  		return dto.BitBucketResponseBranchCreate{}, err
   224  	}
   225  
   226  	log.Logger().FinishMessage("Create branch")
   227  	return responseObject, nil
   228  }
   229  
   230  // GetBranch creates the branch in API
   231  func (b *BitBucketClient) GetBranch(workspace string, repositorySlug string, branchName string) (dto.BitBucketResponseBranchCreate, error) {
   232  	log.Logger().StartMessage("Get branch")
   233  	if err := b.beforeRequest(); err != nil {
   234  		log.Logger().FinishMessage("Get branch")
   235  		return dto.BitBucketResponseBranchCreate{}, err
   236  	}
   237  
   238  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   239  
   240  	endpoint := fmt.Sprintf("/repositories/%s/%s/refs/branches/%s", workspace, repositorySlug, branchName)
   241  	response, statusCode, err := b.client.Get(endpoint, map[string]string{})
   242  	if err != nil {
   243  		log.Logger().FinishMessage("Get branch")
   244  		return dto.BitBucketResponseBranchCreate{}, err
   245  	}
   246  
   247  	if statusCode == http.StatusNotFound {
   248  		log.Logger().FinishMessage("Get branch")
   249  		return dto.BitBucketResponseBranchCreate{}, errors.New("this branch doesn't exist. ")
   250  	}
   251  
   252  	if statusCode == http.StatusForbidden {
   253  		log.Logger().FinishMessage("Get branch")
   254  		return dto.BitBucketResponseBranchCreate{}, errors.New("action is not permitted. ")
   255  	}
   256  
   257  	responseObject := dto.BitBucketResponseBranchCreate{}
   258  	err = json.Unmarshal(response, &responseObject)
   259  	if err != nil {
   260  		log.Logger().AddError(err).Msg("Error during response unmarshal")
   261  		log.Logger().FinishMessage("Get branch")
   262  		return dto.BitBucketResponseBranchCreate{}, err
   263  	}
   264  
   265  	log.Logger().FinishMessage("Get branch")
   266  	return responseObject, nil
   267  }
   268  
   269  // PullRequestInfo gets the pull-requests information
   270  func (b *BitBucketClient) PullRequestInfo(workspace string, repositorySlug string, pullRequestID int64) (dto.BitBucketPullRequestInfoResponse, error) {
   271  	log.Logger().StartMessage("Get pull-request status")
   272  	if err := b.beforeRequest(); err != nil {
   273  		log.Logger().FinishMessage("Get pull-request status")
   274  		return dto.BitBucketPullRequestInfoResponse{}, err
   275  	}
   276  
   277  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   278  	endpoint := fmt.Sprintf("/repositories/%s/%s/pullrequests/%d", workspace, repositorySlug, pullRequestID)
   279  	response, _, err := b.client.Get(endpoint, map[string]string{})
   280  
   281  	if err != nil {
   282  		log.Logger().FinishMessage("Get pull-request status")
   283  		return dto.BitBucketPullRequestInfoResponse{}, err
   284  	}
   285  
   286  	var responseObject dto.BitBucketPullRequestInfoResponse
   287  	err = json.Unmarshal(response, &responseObject)
   288  	if err != nil {
   289  		log.Logger().FinishMessage("Get pull-request status")
   290  		return dto.BitBucketPullRequestInfoResponse{}, err
   291  	}
   292  
   293  	log.Logger().FinishMessage("Get pull-request status")
   294  	return responseObject, nil
   295  }
   296  
   297  // MergePullRequest merge the selected pull-request
   298  func (b *BitBucketClient) MergePullRequest(workspace string, repositorySlug string, pullRequestID int64, description string, strategy string) (dto.BitBucketPullRequestInfoResponse, error) {
   299  	log.Logger().StartMessage("Merge pull-request")
   300  	if err := b.beforeRequest(); err != nil {
   301  		log.Logger().FinishMessage("Merge pull-request")
   302  		return dto.BitBucketPullRequestInfoResponse{}, err
   303  	}
   304  
   305  	formData := map[string]string{
   306  		"merge_strategy":      strategy,
   307  		"message":             description,
   308  		"close_source_branch": "1",
   309  	}
   310  
   311  	byteString, err := json.Marshal(formData)
   312  	if err != nil {
   313  		log.Logger().FinishMessage("Merge pull-request")
   314  		return dto.BitBucketPullRequestInfoResponse{}, err
   315  	}
   316  
   317  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   318  	endpoint := fmt.Sprintf("/repositories/%s/%s/pullrequests/%d/merge?async=false", workspace, repositorySlug, pullRequestID)
   319  
   320  	var dtoResponse = dto.BitBucketPullRequestInfoResponse{}
   321  	response, statusCode, err := b.client.Post(endpoint, byteString, map[string]string{})
   322  	if err != nil {
   323  		log.Logger().FinishMessage("Merge pull-request")
   324  		return dto.BitBucketPullRequestInfoResponse{}, err
   325  	}
   326  
   327  	//In that case the bitbucket accepts our request and the Pull-request will be merged but in async way(even if we specified async=false)
   328  	if statusCode == http.StatusAccepted {
   329  		log.Logger().
   330  			Debug().
   331  			RawJSON("response", response).
   332  			Int("status_code", statusCode).
   333  			Msg("The response with poll link received.")
   334  		log.Logger().FinishMessage("Merge pull-request")
   335  		return dtoResponse, nil
   336  	}
   337  
   338  	if err := json.Unmarshal(response, &dtoResponse); err != nil {
   339  		log.Logger().
   340  			AddError(err).
   341  			RawJSON("response", response).
   342  			Int("status_code", statusCode).
   343  			Msg("Error during the request unmarshal.")
   344  		log.Logger().FinishMessage("Merge pull-request")
   345  		return dto.BitBucketPullRequestInfoResponse{}, err
   346  	}
   347  
   348  	if statusCode == http.StatusBadRequest {
   349  		log.Logger().FinishMessage("Merge pull-request")
   350  		return dto.BitBucketPullRequestInfoResponse{}, fmt.Errorf("bitbucket response with the error: %s", dtoResponse.Error.Message)
   351  	}
   352  
   353  	if statusCode == http.StatusUnauthorized {
   354  		log.Logger().FinishMessage("Merge pull-request")
   355  		return dto.BitBucketPullRequestInfoResponse{}, fmt.Errorf(ErrorMsgNoAccess)
   356  	}
   357  
   358  	if statusCode == http.StatusNotFound {
   359  		log.Logger().FinishMessage("Merge pull-request")
   360  		return dto.BitBucketPullRequestInfoResponse{}, errors.New("selected pull-request was not found :( ")
   361  	}
   362  
   363  	log.Logger().FinishMessage("Merge pull-request")
   364  	return dtoResponse, nil
   365  }
   366  
   367  // ChangePullRequestDestination changes the pull-request destination to selected one
   368  func (b *BitBucketClient) ChangePullRequestDestination(workspace string, repositorySlug string, pullRequestID int64, title string, branchName string) (dto.BitBucketPullRequestInfoResponse, error) {
   369  	log.Logger().StartMessage("Change destination")
   370  	if err := b.beforeRequest(); err != nil {
   371  		log.Logger().FinishMessage("Change destination")
   372  		return dto.BitBucketPullRequestInfoResponse{}, err
   373  	}
   374  
   375  	byteString, err := json.Marshal(dto.BitBucketPullRequestDestinationUpdateRequest{
   376  		Title: title,
   377  		Destination: dto.BitBucketPullRequestDestination{
   378  			Branch: dto.BitBucketPullRequestDestinationBranch{
   379  				Name: branchName,
   380  			},
   381  		},
   382  	})
   383  
   384  	if err != nil {
   385  		log.Logger().FinishMessage("Change destination")
   386  		return dto.BitBucketPullRequestInfoResponse{}, err
   387  	}
   388  
   389  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   390  	endpoint := fmt.Sprintf("/repositories/%s/%s/pullrequests/%d", workspace, repositorySlug, pullRequestID)
   391  
   392  	var dtoResponse = dto.BitBucketPullRequestInfoResponse{}
   393  	response, statusCode, err := b.client.Put(endpoint, byteString, map[string]string{})
   394  	if err != nil {
   395  		log.Logger().FinishMessage("Change destination")
   396  		return dto.BitBucketPullRequestInfoResponse{}, err
   397  	}
   398  
   399  	if err := json.Unmarshal(response, &dtoResponse); err != nil {
   400  		log.Logger().FinishMessage("Change destination")
   401  		return dto.BitBucketPullRequestInfoResponse{}, err
   402  	}
   403  
   404  	if statusCode == http.StatusBadRequest {
   405  		log.Logger().FinishMessage("Change destination")
   406  		return dto.BitBucketPullRequestInfoResponse{}, errors.New(dtoResponse.Error.Message)
   407  	}
   408  
   409  	if statusCode == http.StatusUnauthorized {
   410  		log.Logger().FinishMessage("Change destination")
   411  		return dto.BitBucketPullRequestInfoResponse{}, errors.New(ErrorMsgNoAccess)
   412  	}
   413  
   414  	if statusCode == http.StatusNotFound {
   415  		log.Logger().FinishMessage("Change destination")
   416  		return dto.BitBucketPullRequestInfoResponse{}, errors.New("selected pull-request was not found :( ")
   417  	}
   418  
   419  	var responseObject dto.BitBucketPullRequestInfoResponse
   420  	err = json.Unmarshal(response, &responseObject)
   421  	if err != nil {
   422  		log.Logger().FinishMessage("Change destination")
   423  		return dto.BitBucketPullRequestInfoResponse{}, err
   424  	}
   425  
   426  	log.Logger().FinishMessage("Change destination")
   427  	return responseObject, nil
   428  }
   429  
   430  // CreatePullRequest creates the pull-request
   431  func (b *BitBucketClient) CreatePullRequest(workspace string, repositorySlug string, request dto.BitBucketRequestPullRequestCreate) (dto.BitBucketPullRequestInfoResponse, error) {
   432  	log.Logger().StartMessage("Create pull-request")
   433  	if err := b.beforeRequest(); err != nil {
   434  		log.Logger().FinishMessage("Create pull-request")
   435  		return dto.BitBucketPullRequestInfoResponse{}, err
   436  	}
   437  
   438  	byteString, err := json.Marshal(request)
   439  	if err != nil {
   440  		log.Logger().FinishMessage("Create pull-request")
   441  		return dto.BitBucketPullRequestInfoResponse{}, err
   442  	}
   443  
   444  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   445  	endpoint := fmt.Sprintf("/repositories/%s/%s/pullrequests", workspace, repositorySlug)
   446  
   447  	response, statusCode, err := b.client.Post(endpoint, byteString, map[string]string{})
   448  	if err != nil {
   449  		log.Logger().AddError(err).Msg("Error during the request")
   450  		log.Logger().FinishMessage("Create pull-request")
   451  		return dto.BitBucketPullRequestInfoResponse{}, err
   452  	}
   453  
   454  	var dtoResponse = dto.BitBucketPullRequestInfoResponse{}
   455  	if err := json.Unmarshal(response, &dtoResponse); err != nil {
   456  		log.Logger().AddError(err).Msg("Error during the unmarshal")
   457  		log.Logger().FinishMessage("Create pull-request")
   458  		return dto.BitBucketPullRequestInfoResponse{}, err
   459  	}
   460  
   461  	if statusCode == http.StatusBadRequest {
   462  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Bad request status code")
   463  		log.Logger().FinishMessage("Create pull-request")
   464  		return dto.BitBucketPullRequestInfoResponse{}, errors.New(dtoResponse.Error.Message)
   465  	}
   466  
   467  	if statusCode == http.StatusUnauthorized {
   468  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Unauthorized status code")
   469  		log.Logger().FinishMessage("Create pull-request")
   470  		return dto.BitBucketPullRequestInfoResponse{}, errors.New(ErrorMsgNoAccess)
   471  	}
   472  
   473  	if statusCode == http.StatusNotFound {
   474  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Not found status code")
   475  		log.Logger().FinishMessage("Create pull-request")
   476  		return dto.BitBucketPullRequestInfoResponse{}, errors.New("endpoint or selected branch was not found :( ")
   477  	}
   478  
   479  	log.Logger().FinishMessage("Create pull-request")
   480  	return dtoResponse, nil
   481  }
   482  
   483  // RunPipeline runs the selected custom pipeline
   484  func (b *BitBucketClient) RunPipeline(workspace string, repositorySlug string, request dto.BitBucketRequestRunPipeline) (dto.BitBucketResponseRunPipeline, error) {
   485  	log.Logger().StartMessage("Run pipeline")
   486  	if err := b.beforeRequest(); err != nil {
   487  		log.Logger().FinishMessage("Run pipeline")
   488  		return dto.BitBucketResponseRunPipeline{}, err
   489  	}
   490  
   491  	if len(request.Variables) == 0 {
   492  		request.Variables = []dto.Variable{}
   493  	}
   494  
   495  	byteString, err := json.Marshal(request)
   496  	if err != nil {
   497  		log.Logger().FinishMessage("Run pipeline")
   498  		return dto.BitBucketResponseRunPipeline{}, err
   499  	}
   500  
   501  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   502  	endpoint := fmt.Sprintf("/repositories/%s/%s/pipelines/", workspace, repositorySlug)
   503  	response, statusCode, err := b.client.Post(endpoint, byteString, map[string]string{})
   504  	if err != nil {
   505  		log.Logger().FinishMessage("Run pipeline")
   506  		return dto.BitBucketResponseRunPipeline{}, err
   507  	}
   508  
   509  	fmt.Println(string(response))
   510  	var responseObject dto.BitBucketResponseRunPipeline
   511  	err = json.Unmarshal(response, &responseObject)
   512  	if err != nil {
   513  		log.Logger().FinishMessage("Run pipeline")
   514  		return dto.BitBucketResponseRunPipeline{}, err
   515  	}
   516  
   517  	if statusCode == http.StatusBadRequest {
   518  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Bad request status code")
   519  		log.Logger().FinishMessage("Run pipeline")
   520  		return dto.BitBucketResponseRunPipeline{}, fmt.Errorf("%s. (%s)", responseObject.Error.Message, responseObject.Error.Detail)
   521  	}
   522  
   523  	if statusCode == http.StatusUnauthorized {
   524  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Unauthorized status code")
   525  		log.Logger().FinishMessage("Run pipeline")
   526  		return dto.BitBucketResponseRunPipeline{}, errors.New(ErrorMsgNoAccess)
   527  	}
   528  
   529  	if statusCode == http.StatusNotFound {
   530  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Not found status code")
   531  		log.Logger().FinishMessage("Run pipeline")
   532  		return dto.BitBucketResponseRunPipeline{}, errors.New("endpoint or selected branch was not found :( ")
   533  	}
   534  
   535  	log.Logger().FinishMessage("Run pipeline")
   536  	return responseObject, nil
   537  }
   538  
   539  // GetDefaultReviewers gets default reviewers
   540  func (b *BitBucketClient) GetDefaultReviewers(workspace string, repositorySlug string) (dto.BitBucketResponseDefaultReviewers, error) {
   541  	if err := b.beforeRequest(); err != nil {
   542  		return dto.BitBucketResponseDefaultReviewers{}, err
   543  	}
   544  
   545  	b.client.SetBaseURL(DefaultBitBucketBaseAPIUrl)
   546  	endpoint := fmt.Sprintf("/repositories/%s/%s/default-reviewers", workspace, repositorySlug)
   547  
   548  	response, statusCode, err := b.client.Get(endpoint, map[string]string{})
   549  	if err != nil {
   550  		log.Logger().
   551  			AddError(err).
   552  			RawJSON("response", response).
   553  			Int("status_code", statusCode).
   554  			Msg("Error during the request.")
   555  		return dto.BitBucketResponseDefaultReviewers{}, err
   556  	}
   557  
   558  	var dtoResponse = dto.BitBucketResponseDefaultReviewers{}
   559  	if err := json.Unmarshal(response, &dtoResponse); err != nil {
   560  		log.Logger().AddError(err).Msg("Error during the unmarshal")
   561  		return dto.BitBucketResponseDefaultReviewers{}, err
   562  	}
   563  
   564  	if statusCode == http.StatusUnauthorized {
   565  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Unauthorized status code")
   566  		return dto.BitBucketResponseDefaultReviewers{}, errors.New(ErrorMsgNoAccess)
   567  	}
   568  
   569  	if statusCode == http.StatusNotFound {
   570  		log.Logger().Warn().Int("status_code", statusCode).Str("response", string(response)).Msg("Not found status code")
   571  		return dto.BitBucketResponseDefaultReviewers{}, errors.New("endpoint or selected branch was not found :( ")
   572  	}
   573  
   574  	return dtoResponse, nil
   575  }