From 6b91b87dee46cf0c0599f5a0db86168a13af4ac4 Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Wed, 27 Dec 2017 15:20:32 +0100
Subject: [PATCH] feat: stop updating PR if edited

Previously, Renovate would attempt to keep a branch up to date even if users had edited it. e.g. adding commits on top of the existing branch if newer versions were released. Now, Renovate adds a warning comment if a user has edited a branch, making it clear that responsibility for the branch is over to them and how they can undo this.

Closes #653
---
 lib/manager/index.js              |  4 ++--
 lib/workers/branch/index.js       | 18 +++++++++++++++++-
 test/workers/branch/index.spec.js |  8 ++++++++
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/lib/manager/index.js b/lib/manager/index.js
index a64be4cc91..e9672c8d79 100644
--- a/lib/manager/index.js
+++ b/lib/manager/index.js
@@ -108,7 +108,7 @@ async function getUpdatedPackageFiles(config) {
         newContent = await bazelHelper.setNewValue(existingContent, upgrade);
       }
       if (!newContent) {
-        if (config.parentBranch && config.canRebase) {
+        if (config.parentBranch) {
           logger.info('Rebasing branch after error updating content');
           return getUpdatedPackageFiles({
             ...config,
@@ -118,7 +118,7 @@ async function getUpdatedPackageFiles(config) {
         throw new Error('Error updating branch content and cannot rebase');
       }
       if (newContent !== existingContent) {
-        if (config.parentBranch && config.canRebase) {
+        if (config.parentBranch) {
           // This ensure it's always 1 commit from Renovate
           logger.info('Need to update package file so will rebase first');
           return getUpdatedPackageFiles({
diff --git a/lib/workers/branch/index.js b/lib/workers/branch/index.js
index 19fdd88224..84f8186070 100644
--- a/lib/workers/branch/index.js
+++ b/lib/workers/branch/index.js
@@ -30,7 +30,7 @@ async function processBranch(branchConfig) {
     logger.info(`Branch has ${dependencies.length} upgrade(s)`);
 
     // Check if branch already existed
-    const pr = await prAlreadyExisted(config);
+    let pr = await prAlreadyExisted(config);
     if (pr) {
       logger.info(
         { prTitle: config.prTitle },
@@ -60,6 +60,22 @@ async function processBranch(branchConfig) {
       await platform.ensureComment(pr.number, subject, content);
       return 'already-existed';
     }
+    logger.debug('Checking if PR has been edited');
+    pr = await platform.findPr(config.branchName, config.prTitle, 'open');
+    if (pr) {
+      logger.debug('Open PR already exists');
+      pr = await platform.getPr(pr.number);
+      if (!pr.canRebase) {
+        logger.info('PR has been edited');
+        const subject = 'PR has been edited';
+        let content =
+          'As this PR has been edited, Renovate will stop updating it in order to not cause any conflicts or other problems.';
+        content +=
+          ' If you wish to abandon your edits and have Renovate recreate this PR then you should rename this PR and then close it.';
+        await platform.ensureComment(pr.number, subject, content);
+        return 'pr-edited';
+      }
+    }
 
     // Check schedule
     config.isScheduledNow = isScheduledNow(config);
diff --git a/test/workers/branch/index.spec.js b/test/workers/branch/index.spec.js
index d8d583234a..90acab8a1e 100644
--- a/test/workers/branch/index.spec.js
+++ b/test/workers/branch/index.spec.js
@@ -82,6 +82,14 @@ describe('workers/branch', () => {
       await branchWorker.processBranch(config);
       expect(parent.getParentBranch.mock.calls.length).toBe(0);
     });
+    it('skips branch if edited PR found', async () => {
+      schedule.isScheduledNow.mockReturnValueOnce(false);
+      platform.branchExists.mockReturnValueOnce(true);
+      platform.findPr.mockReturnValueOnce({});
+      platform.getPr.mockReturnValueOnce({ canRebase: false });
+      const res = await branchWorker.processBranch(config);
+      expect(res).toEqual('pr-edited');
+    });
     it('returns if no work', async () => {
       manager.getUpdatedPackageFiles.mockReturnValueOnce({
         updatedPackageFiles: [],
-- 
GitLab