From d66dea7ec3cecc4323d3ced0e362ab7fa4868c6d Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@arkins.net>
Date: Thu, 25 Jan 2018 13:36:21 +0100
Subject: [PATCH] feat: verify status check (GitHub) (#1444)

Adds a `renovate/verify` status check for those migrating and looking for familiarity. Better to check the GPG verified commit, as mentioned in the associated doc.
---
 lib/config/definitions.js                     |  6 ++++++
 lib/platform/github/index.js                  | 19 ++++++++++++++++++-
 lib/workers/pr/index.js                       |  9 ++++++++-
 .../repository/onboarding/branch/create.js    | 10 +++++++---
 .../github/__snapshots__/index.spec.js.snap   | 11 +++++++++++
 test/platform/github/index.spec.js            | 10 +++++++++-
 .../pr/__snapshots__/index.spec.js.snap       |  6 ++++++
 .../branch/__snapshots__/index.spec.js.snap   |  1 +
 .../2017-10-05-configuration-options.md       | 11 +++++++++++
 9 files changed, 77 insertions(+), 6 deletions(-)

diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index 10a65d0233..2d235849e0 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -528,6 +528,12 @@ const options = [
     type: 'boolean',
     default: false,
   },
+  {
+    name: 'statusCheckVerify',
+    description: '`Set a "renovate/verify" status check for all PRs`',
+    type: 'boolean',
+    default: false,
+  },
   {
     name: 'unpublishSafe',
     description: 'Set a status check for unpublish-safe upgrades',
diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js
index 2fc2bd098a..a689e01bf8 100644
--- a/lib/platform/github/index.js
+++ b/lib/platform/github/index.js
@@ -678,7 +678,14 @@ async function findPr(branchName, prTitle, state = 'all') {
 }
 
 // Creates PR and returns PR number
-async function createPr(branchName, title, body, labels, useDefaultBranch) {
+async function createPr(
+  branchName,
+  title,
+  body,
+  labels,
+  useDefaultBranch,
+  statusCheckVerify
+) {
   const base = useDefaultBranch ? config.defaultBranch : config.baseBranch;
   // Include the repository owner to handle forkMode and regular mode
   const head = `${config.repository.split('/')[0]}:${branchName}`;
@@ -701,6 +708,16 @@ async function createPr(branchName, title, body, labels, useDefaultBranch) {
   )).body;
   pr.displayNumber = `Pull Request #${pr.number}`;
   await addLabels(pr.number, labels);
+  if (statusCheckVerify) {
+    logger.debug('Setting statusCheckVerify');
+    await setBranchStatus(
+      branchName,
+      'renovate/verify',
+      'Renovate verified pull request',
+      'success',
+      'https://renovateapp.com'
+    );
+  }
   return pr;
 }
 
diff --git a/lib/workers/pr/index.js b/lib/workers/pr/index.js
index 8bfdd4d85f..6be25df16d 100644
--- a/lib/workers/pr/index.js
+++ b/lib/workers/pr/index.js
@@ -177,7 +177,14 @@ async function ensurePr(prConfig) {
     logger.info({ branchName, prTitle }, `Creating PR`);
     let pr;
     try {
-      pr = await platform.createPr(branchName, prTitle, prBody, config.labels);
+      pr = await platform.createPr(
+        branchName,
+        prTitle,
+        prBody,
+        config.labels,
+        false,
+        config.statusCheckVerify
+      );
     } catch (err) {
       logger.warn({ err }, `Failed to create PR`);
       return null;
diff --git a/lib/workers/repository/onboarding/branch/create.js b/lib/workers/repository/onboarding/branch/create.js
index 2b7938a990..cc0cafa1b6 100644
--- a/lib/workers/repository/onboarding/branch/create.js
+++ b/lib/workers/repository/onboarding/branch/create.js
@@ -5,9 +5,13 @@ async function createOnboardingBranch() {
   };
   try {
     logger.debug('Checking for greenkeeper config');
-    const { label, branchName, ignore } = JSON.parse(
-      await platform.getFile('package.json')
-    ).greenkeeper;
+
+    const greenkeeperConfig = JSON.parse(await platform.getFile('package.json'))
+      .greenkeeper;
+    if (greenkeeperConfig) {
+      renovateJson.statusCheckVerify = true;
+    }
+    const { label, branchName, ignore } = greenkeeperConfig;
     if (label) {
       logger.info({ label }, 'Migrating Greenkeeper label');
       renovateJson.labels = [String(label).replace('greenkeeper', 'renovate')];
diff --git a/test/platform/github/__snapshots__/index.spec.js.snap b/test/platform/github/__snapshots__/index.spec.js.snap
index 1be12fb0c2..8ac0e42395 100644
--- a/test/platform/github/__snapshots__/index.spec.js.snap
+++ b/test/platform/github/__snapshots__/index.spec.js.snap
@@ -228,6 +228,17 @@ Array [
       ],
     },
   ],
+  Array [
+    "repos/some/repo/statuses/some-sha",
+    Object {
+      "body": Object {
+        "context": "renovate/verify",
+        "description": "Renovate verified pull request",
+        "state": "success",
+        "target_url": "https://renovateapp.com",
+      },
+    },
+  ],
 ]
 `;
 
diff --git a/test/platform/github/index.spec.js b/test/platform/github/index.spec.js
index 71341d5aa0..f91dee47a3 100644
--- a/test/platform/github/index.spec.js
+++ b/test/platform/github/index.spec.js
@@ -1116,11 +1116,19 @@ describe('platform/github', () => {
           number: 123,
         },
       }));
+      get.mockImplementationOnce(() => ({
+        body: {
+          object: { sha: 'some-sha' },
+        },
+      }));
+      // res.body.object.sha
       const pr = await github.createPr(
         'some-branch',
         'The Title',
         'Hello world',
-        ['deps', 'renovate']
+        ['deps', 'renovate'],
+        false,
+        true
       );
       expect(pr).toMatchSnapshot();
       expect(get.post.mock.calls).toMatchSnapshot();
diff --git a/test/workers/pr/__snapshots__/index.spec.js.snap b/test/workers/pr/__snapshots__/index.spec.js.snap
index d119220c58..9695c5f136 100644
--- a/test/workers/pr/__snapshots__/index.spec.js.snap
+++ b/test/workers/pr/__snapshots__/index.spec.js.snap
@@ -42,6 +42,8 @@ Array [
 <hr />
 <p>This MR has been generated by <a href=\\"https://renovateapp.com\\">Renovate Bot</a>.</p>",
   Array [],
+  false,
+  false,
 ]
 `;
 
@@ -69,6 +71,8 @@ Array [
 
 This PR has been generated by [Renovate Bot](https://renovateapp.com).",
   Array [],
+  false,
+  false,
 ]
 `;
 
@@ -124,5 +128,7 @@ Array [
 
 This PR has been generated by [Renovate Bot](https://renovateapp.com).",
   Array [],
+  false,
+  false,
 ]
 `;
diff --git a/test/workers/repository/onboarding/branch/__snapshots__/index.spec.js.snap b/test/workers/repository/onboarding/branch/__snapshots__/index.spec.js.snap
index d7cb31bdab..cb9927639f 100644
--- a/test/workers/repository/onboarding/branch/__snapshots__/index.spec.js.snap
+++ b/test/workers/repository/onboarding/branch/__snapshots__/index.spec.js.snap
@@ -5,6 +5,7 @@ exports[`workers/repository/onboarding/branch checkOnboardingBranch creates onbo
   \\"extends\\": [
     \\"config:base\\"
   ],
+  \\"statusCheckVerify\\": true,
   \\"labels\\": [
     \\"renovate\\"
   ],
diff --git a/website/docs/_posts/2017-10-05-configuration-options.md b/website/docs/_posts/2017-10-05-configuration-options.md
index 4db8319de3..d834cfb375 100644
--- a/website/docs/_posts/2017-10-05-configuration-options.md
+++ b/website/docs/_posts/2017-10-05-configuration-options.md
@@ -945,6 +945,17 @@ If set to true, it will separate minor and patch updates into separate branches.
 
 By default, Renovate won't distinguish between "patch" (e.g. 1.0.x) and "minor" (e.g. 1.x.0) releases - groups them together. e.g. if you are running version 1.0.0 of a package and both versions 1.0.1 and 1.1.0 are available then Renovate will raise a single PR for version 1.1.0. If you wish to distinguish between patch and minor upgrades, for example if you wish to automerge patch but not minor, then you can set this option to `true`.
 
+## statusCheckVerify
+
+Set a "renovate/verify" status check for all PRs
+
+| name    | value   |
+| ------- | ------- |
+| type    | boolean |
+| default | false   |
+
+This feature is added for people migrating from alternative services who are used to seeing a "verify" status check on PRs. If you'd like to use this then go ahead, but otherwise we recommend it's more secure to look for Renovate's [GPG Verified Commits](https://github.com/blog/2144-gpg-signature-verification) instead, because those cannot be spoofed by any other person or service (unlike status checks).
+
 ## supportPolicy
 
 Dependency support policy, e.g. used for LTS vs non-LTS etc (node-only)
-- 
GitLab