From 21e1f1ff3edf975a26a4f2d846bc47bdad5ce5fd Mon Sep 17 00:00:00 2001
From: Sergio Zharinov <zharinov@users.noreply.github.com>
Date: Fri, 28 Aug 2020 17:22:14 +0400
Subject: [PATCH] feat(worker): Enforce limits at PR creation time (#7099)

---
 lib/workers/branch/index.spec.ts | 16 ++++++++++++++++
 lib/workers/branch/index.ts      |  6 +++++-
 lib/workers/common.ts            |  1 +
 lib/workers/pr/index.spec.ts     | 10 ++++++++++
 lib/workers/pr/index.ts          |  6 +++++-
 5 files changed, 37 insertions(+), 2 deletions(-)

diff --git a/lib/workers/branch/index.spec.ts b/lib/workers/branch/index.spec.ts
index 13f94011ed..43329a15d8 100644
--- a/lib/workers/branch/index.spec.ts
+++ b/lib/workers/branch/index.spec.ts
@@ -215,6 +215,22 @@ describe('workers/branch', () => {
         'pr-limit-reached'
       );
     });
+    it('returns if pr creation limit exceeded and branch exists', async () => {
+      getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({
+        ...updatedPackageFiles,
+      });
+      npmPostExtract.getAdditionalFiles.mockResolvedValueOnce({
+        artifactErrors: [],
+        updatedArtifacts: [],
+      });
+      git.branchExists.mockResolvedValue(true);
+      prWorker.ensurePr.mockResolvedValueOnce({
+        prResult: PrResult.LimitReached,
+      });
+      expect(await branchWorker.processBranch(config, true)).toEqual(
+        'pr-limit-reached'
+      );
+    });
     it('returns if commit limit exceeded', async () => {
       getUpdated.getUpdatedPackageFiles.mockResolvedValueOnce({
         ...updatedPackageFiles,
diff --git a/lib/workers/branch/index.ts b/lib/workers/branch/index.ts
index f32c5887e9..1a903e6e55 100644
--- a/lib/workers/branch/index.ts
+++ b/lib/workers/branch/index.ts
@@ -560,7 +560,11 @@ export async function processBranch(
     logger.debug(
       `There are ${config.errors.length} errors and ${config.warnings.length} warnings`
     );
-    const { prResult: result, pr } = await ensurePr(config);
+    const { prResult: result, pr } = await ensurePr(config, prLimitReached);
+    if (result === PrResult.LimitReached) {
+      logger.debug('Reached PR limit - skipping PR creation');
+      return 'pr-limit-reached';
+    }
     // TODO: ensurePr should check for automerge itself
     if (result === PrResult.AwaitingApproval) {
       return 'needs-pr-approval';
diff --git a/lib/workers/common.ts b/lib/workers/common.ts
index b0673050a3..5b65c79364 100644
--- a/lib/workers/common.ts
+++ b/lib/workers/common.ts
@@ -72,6 +72,7 @@ export enum PrResult {
   ErrorAlreadyExists = 'ErrorAlreadyExists',
   NotUpdated = 'NotUpdated',
   Updated = 'Updated',
+  LimitReached = 'LimitReached',
 }
 
 export type ProcessBranchResult =
diff --git a/lib/workers/pr/index.spec.ts b/lib/workers/pr/index.spec.ts
index 80244ccf65..24cbecbc1a 100644
--- a/lib/workers/pr/index.spec.ts
+++ b/lib/workers/pr/index.spec.ts
@@ -261,6 +261,16 @@ describe('workers/pr', () => {
       expect(platform.createPr.mock.calls[0]).toMatchSnapshot();
       existingPr.body = platform.createPr.mock.calls[0][0].prBody;
     });
+    it('should not create PR if limit is reached', async () => {
+      platform.getBranchStatus.mockResolvedValueOnce(BranchStatus.green);
+      config.logJSON = await getChangeLogJSON(config);
+      config.prCreation = 'status-success';
+      config.automerge = true;
+      config.schedule = ['before 5am'];
+      const { prResult } = await prWorker.ensurePr(config, true);
+      expect(prResult).toEqual(PrResult.LimitReached);
+      expect(platform.createPr.mock.calls).toBeEmpty();
+    });
     it('should create group PR', async () => {
       config.upgrades = config.upgrades.concat([
         {
diff --git a/lib/workers/pr/index.ts b/lib/workers/pr/index.ts
index 4e42001f63..fe7771f971 100644
--- a/lib/workers/pr/index.ts
+++ b/lib/workers/pr/index.ts
@@ -96,7 +96,8 @@ export async function addAssigneesReviewers(
 
 // Ensures that PR exists with matching title/body
 export async function ensurePr(
-  prConfig: BranchConfig
+  prConfig: BranchConfig,
+  prLimitReached?: boolean
 ): Promise<{
   prResult: PrResult;
   pr?: Pr;
@@ -359,6 +360,9 @@ export async function ensurePr(
             config.automergeType === 'pr' &&
             config.gitLabAutomerge,
         };
+        if (prLimitReached) {
+          return { prResult: PrResult.LimitReached };
+        }
         pr = await platform.createPr({
           branchName,
           targetBranch: config.baseBranch,
-- 
GitLab