From 96c06e58e6220efdfffdc4ec1dd7b5b8af2e97b1 Mon Sep 17 00:00:00 2001
From: Adam Setch <adam.setch@outlook.com>
Date: Mon, 26 Jun 2023 07:33:24 -0400
Subject: [PATCH] feat(platform/bitbucket): handle author is also default
 reviewer (#22978)

---
 lib/modules/platform/bitbucket/index.spec.ts | 50 ++++++++++++++++++++
 lib/modules/platform/bitbucket/index.ts      | 26 +++++++---
 2 files changed, 70 insertions(+), 6 deletions(-)

diff --git a/lib/modules/platform/bitbucket/index.spec.ts b/lib/modules/platform/bitbucket/index.spec.ts
index 4e1cd43190..40a37e4bf1 100644
--- a/lib/modules/platform/bitbucket/index.spec.ts
+++ b/lib/modules/platform/bitbucket/index.spec.ts
@@ -1015,6 +1015,56 @@ describe('modules/platform/bitbucket/index', () => {
       ).rejects.toThrow(new Error('Response code 401 (Unauthorized)'));
     });
 
+    it('removes reviewer if they are also the author of the pr', async () => {
+      const reviewers = [
+        {
+          user: {
+            display_name: 'Bob Smith',
+            uuid: '{d2238482-2e9f-48b3-8630-de22ccb9e42f}',
+            account_id: '123',
+          },
+        },
+        {
+          user: {
+            display_name: 'Jane Smith',
+            uuid: '{90b6646d-1724-4a64-9fd9-539515fe94e9}',
+            account_id: '456',
+          },
+        },
+      ];
+      const scope = await initRepoMock();
+      scope
+        .get(
+          '/2.0/repositories/some/repo/effective-default-reviewers?pagelen=100'
+        )
+        .reply(200, {
+          values: reviewers,
+        })
+        .post('/2.0/repositories/some/repo/pullrequests')
+        .reply(400, {
+          type: 'error',
+          error: {
+            fields: {
+              reviewers: [
+                'Jane Smith is the author and cannot be included as a reviewer.',
+              ],
+            },
+          },
+        })
+        .post('/2.0/repositories/some/repo/pullrequests')
+        .reply(200, { id: 5 });
+      const pr = await bitbucket.createPr({
+        sourceBranch: 'branch',
+        targetBranch: 'master',
+        prTitle: 'title',
+        prBody: 'body',
+        platformOptions: {
+          bbUseDefaultReviewers: true,
+        },
+      });
+      expect(pr?.number).toBe(5);
+    });
+
     it('rethrows exception when PR create error due to unknown reviewers error', async () => {
       const reviewer = {
         user: {
diff --git a/lib/modules/platform/bitbucket/index.ts b/lib/modules/platform/bitbucket/index.ts
index b36808e4e5..3bfee11463 100644
--- a/lib/modules/platform/bitbucket/index.ts
+++ b/lib/modules/platform/bitbucket/index.ts
@@ -719,9 +719,15 @@ async function sanitizeReviewers(
   if (err.statusCode === 400 && err.body?.error?.fields?.reviewers) {
     const sanitizedReviewers: Account[] = [];
 
+    const MSG_AUTHOR_AND_REVIEWER =
+      'is the author and cannot be included as a reviewer.';
+    const MSG_MALFORMED_REVIEWERS_LIST = 'Malformed reviewers list';
+    const MSG_NOT_WORKSPACE_MEMBER =
+      'is not a member of this workspace and cannot be added to this pull request';
+
     for (const msg of err.body.error.fields.reviewers) {
       // Bitbucket returns a 400 if any of the PR reviewer accounts are now inactive (ie: disabled/suspended)
-      if (msg === 'Malformed reviewers list') {
+      if (msg === MSG_MALFORMED_REVIEWERS_LIST) {
         logger.debug(
           { err },
           'PR contains reviewers that may be either inactive or no longer a member of this workspace. Will try setting only active reviewers'
@@ -741,11 +747,7 @@ async function sanitizeReviewers(
           }
         }
         // Bitbucket returns a 400 if any of the PR reviewer accounts are no longer members of this workspace
-      } else if (
-        msg.endsWith(
-          'is not a member of this workspace and cannot be added to this pull request'
-        )
-      ) {
+      } else if (msg.endsWith(MSG_NOT_WORKSPACE_MEMBER)) {
         logger.debug(
           { err },
           'PR contains reviewer accounts which are no longer member of this workspace. Will try setting only member reviewers'
@@ -757,6 +759,17 @@ async function sanitizeReviewers(
             sanitizedReviewers.push(reviewer);
           }
         }
+      } else if (msg.endsWith(MSG_AUTHOR_AND_REVIEWER)) {
+        logger.debug(
+          { err },
+          'PR contains reviewer accounts which are also the author. Will try setting only non-author reviewers'
+        );
+        const author = msg.replace(MSG_AUTHOR_AND_REVIEWER, '').trim();
+        for (const reviewer of reviewers) {
+          if (reviewer.display_name !== author) {
+            sanitizedReviewers.push(reviewer);
+          }
+        }
       } else {
         return undefined;
       }
@@ -822,6 +835,7 @@ export async function createPr({
     ).body;
     reviewers = reviewersResponse.values.map((reviewer: EffectiveReviewer) => ({
       uuid: reviewer.user.uuid,
+      display_name: reviewer.user.display_name,
     }));
   }
 
-- 
GitLab