Repository: JasonEtco/todo
Pull request #192 (2019-02-08 21:32:16)

Upgrade to Probot@8 and @octokit/rest@16
This PR updates TODO to a new major version of Probot and `@octokit/rest`. The main motivation is for some performance improvements in Probot 8, which required some work to get the Octokit usage up to date.

Assuming everything works fine (tests are passing so thats a good sign) this should be an easy merge 😊 

cc @gr2m


Patch:
diff --git a/bin/todo.js b/bin/todo.js
index 0619506..13fd39d 100755
--- a/bin/todo.js
+++ b/bin/todo.js
@@ -2,11 +2,13 @@
 
 const program = require('commander')
 const chalk = require('chalk')
-const octokit = require('@octokit/rest')()
+const GitHubAPI = require('@octokit/rest')
 const pushHandler = require('../lib/push-handler')
 const fs = require('fs')
 const path = require('path')
 
+const octokit = new GitHubAPI()
+
 program
   .option('-o, --owner <owner>', 'owner')
   .option('-r, --repo <repo>', 'repo')
@@ -22,7 +24,7 @@ if (file) {
   octokit.gitdata.getCommit = () => ({ data: { parents: [] } })
 }
 octokit.issues.create = issue => issues.push(issue)
-octokit.search.issues = () => ({ data: { total_count: 0 } })
+octokit.search.issuesAndPullRequests = () => ({ data: { total_count: 0 } })
 
 const context = {
   event: 'push',
diff --git a/codecov.yml b/codecov.yml
index 426318b..477ee9f 100644
--- a/codecov.yml
+++ b/codecov.yml
@@ -8,6 +8,4 @@ coverage:
       default:
         threshold: 3
 
-comment:
-  layout: diff
-  require_changes: yes
+comment: false
\ No newline at end of file
diff --git a/lib/issue-rename-handler.js b/lib/issue-rename-handler.js
index 450e0a4..976fb62 100644
--- a/lib/issue-rename-handler.js
+++ b/lib/issue-rename-handler.js
@@ -1,5 +1,8 @@
 const { titleChange } = require('./templates')
 
+/**
+ * @param {import('probot').Context} context
+ */
 module.exports = async context => {
   const { issue, changes, sender } = context.payload
   const app = process.env.APP_NAME + '[bot]'
@@ -7,7 +10,7 @@ module.exports = async context => {
   if (sender.login !== app && issue.user.login === app && changes.title) {
     context.log(`Renaming issue #${issue.number} in ${context.repo().owner}/${context.repo().repo}`)
     return Promise.all([
-      context.github.issues.edit(context.issue({ title: changes.title.from })),
+      context.github.issues.update(context.issue({ title: changes.title.from })),
       context.github.issues.createComment(context.issue({
         body: titleChange()
       }))
diff --git a/lib/pull-request-handler.js b/lib/pull-request-handler.js
index 173e720..c0fa21c 100644
--- a/lib/pull-request-handler.js
+++ b/lib/pull-request-handler.js
@@ -1,15 +1,14 @@
 const { comment } = require('./templates')
 const { lineBreak } = require('./utils/helpers')
 const mainLoop = require('./utils/main-loop')
-const avoidReplicationLag = require('./utils/avoid-replication-lag')
 
+/**
+ * @param {import('probot').Context} context
+ */
 module.exports = async context => {
-  const {data: comments} = await context.github.issues.getComments(context.issue({}))
+  const {data: comments} = await context.github.issues.listComments(context.issue())
   const { number } = context.issue()
 
-  // Register the hook
-  context.github.hook.before('request', avoidReplicationLag())
-
   return mainLoop(context, async ({
     title,
     keyword,
diff --git a/lib/pull-request-merged-handler.js b/lib/pull-request-merged-handler.js
index 38f8070..bab7cbe 100644
--- a/lib/pull-request-merged-handler.js
+++ b/lib/pull-request-merged-handler.js
@@ -3,14 +3,14 @@ const reopenClosed = require('./utils/reopen-closed')
 const { assignFlow, lineBreak, truncate } = require('./utils/helpers')
 const { issueFromMerge } = require('./templates')
 const mainLoop = require('./utils/main-loop')
-const avoidReplicationLag = require('./utils/avoid-replication-lag')
 
+/**
+ * @param {import('probot').Context} context
+ */
 module.exports = async context => {
   // Don't act on PRs that were close but not merged
   if (!context.payload.pull_request.merged) return
 
-  context.github.hook.before('request', avoidReplicationLag())
-
   return mainLoop(context, async ({
     title,
     config,
diff --git a/lib/push-handler.js b/lib/push-handler.js
index d17a10a..8f09bd3 100644
--- a/lib/push-handler.js
+++ b/lib/push-handler.js
@@ -2,20 +2,19 @@ const checkForDuplicateIssue = require('./utils/check-for-duplicate-issue')
 const { assignFlow, lineBreak, truncate } = require('./utils/helpers')
 const reopenClosed = require('./utils/reopen-closed')
 const { issue } = require('./templates')
-
-const avoidReplicationLag = require('./utils/avoid-replication-lag')
 const mainLoop = require('./utils/main-loop')
 
+/**
+ * @param {import('probot').Context} context
+ */
 module.exports = async context => {
   // Only trigger push handler on pushes to master
   if (context.payload.ref !== `refs/heads/${context.payload.repository.master_branch}`) {
     return
   }
 
-  context.github.hook.before('request', avoidReplicationLag())
-
   // Do not trigger on merge commits
-  const commit = await context.github.gitdata.getCommit(context.repo({commit_sha: context.payload.head_commit.id}))
+  const commit = await context.github.git.getCommit(context.repo({commit_sha: context.payload.head_commit.id}))
   if (commit.data.parents.length > 1) return
 
   return mainLoop(context, async ({
diff --git a/lib/utils/avoid-replication-lag.js b/lib/utils/avoid-replication-lag.js
deleted file mode 100644
index 9698fe3..0000000
--- a/lib/utils/avoid-replication-lag.js
+++ /dev/null
@@ -1,13 +0,0 @@
-const sleep = timeout => new Promise(resolve => setTimeout(resolve, timeout))
-
-module.exports = function avoidReplicationLag () {
-  let shouldSleep = true
-
-  return async (options) => {
-    // Only GET requests are affected by replication lag
-    if (shouldSleep && options.method === 'GET') {
-      await sleep(1000)
-    }
-    shouldSleep = false
-  }
-}
diff --git a/lib/utils/check-for-duplicate-issue.js b/lib/utils/check-for-duplicate-issue.js
index 83e33e3..93f9d4d 100644
--- a/lib/utils/check-for-duplicate-issue.js
+++ b/lib/utils/check-for-duplicate-issue.js
@@ -1,10 +1,10 @@
 /**
  * Checks to see if an issue already exists with the given title.
- * @param {object} context - Probot context object
+ * @param {import('probot').Context} context - Probot context object
  * @param {string} title - An issue title
  */
 module.exports = async (context, title) => {
-  const search = await context.github.search.issues({
+  const search = await context.github.search.issuesAndPullRequests({
     q: `${title} in:title repo:${context.payload.repository.full_name}`,
     per_page: 100
   })
diff --git a/lib/utils/generate-label.js b/lib/utils/generate-label.js
index f61db09..0e6dfce 100644
--- a/lib/utils/generate-label.js
+++ b/lib/utils/generate-label.js
@@ -1,6 +1,6 @@
 /**
  * Generate an array of labels based on the config
- * @param {object} context - Probot context object
+ * @param {import('probot').Context} context - Probot context object
  * @param {object} cfg - Config object
  */
 module.exports = async (context, cfg) => {
diff --git a/lib/utils/get-diff.js b/lib/utils/get-diff.js
index 87c5111..a5c24d7 100644
--- a/lib/utils/get-diff.js
+++ b/lib/utils/get-diff.js
@@ -1,5 +1,6 @@
 /**
  * Gets the diff of the commit or pull request as a string
+ * @param {import('probot').Context} context
  * @returns {string}
  */
 module.exports = async context => {
@@ -11,7 +12,7 @@ module.exports = async context => {
       headers: { Accept: 'application/vnd.github.diff' }
     }))).data
   } else {
-    diff = (await context.github.pullRequests.get(context.issue({
+    diff = (await context.github.pulls.get(context.issue({
       headers: { Accept: 'application/vnd.github.diff' }
     }))).data
   }
diff --git a/lib/utils/reopen-closed.js b/lib/utils/reopen-closed.js
index d271c74..83a0836 100644
--- a/lib/utils/reopen-closed.js
+++ b/lib/utils/reopen-closed.js
@@ -7,7 +7,7 @@ const { reopenClosed } = require('../templates')
  */
 module.exports = async ({context, config, issue}, data) => {
   if (issue.state === 'closed' && config.reopenClosed) {
-    await context.github.issues.edit(context.repo({
+    await context.github.issues.update(context.repo({
       number: issue.number,
       state: 'open'
     }))
diff --git a/package-lock.json b/package-lock.json
index 769ba1c..87c8f87 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -32,35 +32,67 @@
         }
       }
     },
-    "@octokit/rest": {
-      "version": "15.18.0",
-      "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-15.18.0.tgz",
-      "integrity": "sha512-D1dDJMbvT4dok9++vc8uwCr92ndadwfz6vHK+IklzBHKSsuLlhpv2/dzx97Y4aRlm0t74LeXKDp4j0b4M2vmQw==",
+    "@octokit/app": {
+      "version": "2.2.1",
+      "resolved": "https://registry.npmjs.org/@octokit/app/-/app-2.2.1.tgz",
+      "integrity": "sha512-bngDco6DrPMn65mdcf+RhX8bdImrDaY1V/5VZFwYuYhZHRDFDecWSR6cusHwH7G2xjfXhNdIBxbb3PJPoRJxUw==",
       "requires": {
-        "before-after-hook": "^1.1.0",
-        "btoa-lite": "^1.0.0",
-        "debug": "^3.1.0",
-        "http-proxy-agent": "^2.1.0",
-        "https-proxy-agent": "^2.2.0",
-        "lodash": "^4.17.4",
-        "node-fetch": "^2.1.1",
-        "universal-user-agent": "^2.0.0",
+        "@octokit/request": "^2.1.2",
+        "jsonwebtoken": "^8.3.0",
+        "lru-cache": "^5.1.1"
+      }
+    },
+    "@octokit/endpoint": {
+      "version": "3.1.2",
+      "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-3.1.2.tgz",
+      "integrity": "sha512-iRx4kDYybAv9tOrHDBE6HwlgiFi8qmbZl8SHliZWtxbUFuXLZXh2yv8DxGIK9wzD9J0wLDMZneO8vNYJNUSJ9Q==",
+      "requires": {
+        "deepmerge": "3.1.0",
+        "is-plain-object": "^2.0.4",
+        "universal-user-agent": "^2.0.1",
         "url-template": "^2.0.8"
+      }
+    },
+    "@octokit/graphql": {
+      "version": "2.0.1",
+      "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-2.0.1.tgz",
+      "integrity": "sha512-IBNr05yBYqffy9L37Vv3/5xQMw+swmYFtMsuwqUA5vSEUr+s/POf8DOpCaTtS8f7e9k+cEuKLC5AbOoXkdZZOA==",
+      "requires": {
+        "@octokit/request": "^2.1.2"
+      }
+    },
+    "@octokit/plugin-enterprise-compatibility": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-enterprise-compatibility/-/plugin-enterprise-compatibility-1.1.0.tgz",
+      "integrity": "sha512-MT37VSPK0ERG8m6uaK0uimJnVPvo5ecs673yHqp7r2SRis136pWkMWqanJSWGP/TQbWRHKxAvG1U9+3234zMHA=="
+    },
+    "@octokit/plugin-retry": {
+      "version": "2.1.2",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-2.1.2.tgz",
+      "integrity": "sha512-4j1NRkproK9ygE6mqUTNvFVMVpZhzixLCLwOxLUesbN8OBHgGrfKq/Vt9onGD4WHFEUjHOsHS3tehNz8cA7g5g==",
+      "requires": {
+        "bottleneck": "^2.15.3"
+      }
+    },
+    "@octokit/plugin-throttling": {
+      "version": "2.4.0",
+      "resolved": "https://registry.npmjs.org/@octokit/plugin-throttling/-/plugin-throttling-2.4.0.tgz",
+      "integrity": "sha512-0bYfgQdqAtWiqXvS6oKMiousTno+e3pFoaYS57LpAp8p56Far49/vpGvbEvBUuNyoUFgOcTGm5WTpO1IPptHuQ==",
+      "requires": {
+        "bottleneck": "^2.15.3"
+      }
+    },
+    "@octokit/request": {
+      "version": "2.3.0",
+      "resolved": "https://registry.npmjs.org/@octokit/request/-/request-2.3.0.tgz",
+      "integrity": "sha512-5YRqYNZOAaL7+nt7w3Scp6Sz4P2g7wKFP9npx1xdExMomk8/M/ICXVLYVam2wzxeY0cIc6wcKpjC5KI4jiNbGw==",
+      "requires": {
+        "@octokit/endpoint": "^3.1.1",
+        "is-plain-object": "^2.0.4",
+        "node-fetch": "^2.3.0",
+        "universal-user-agent": "^2.0.1"
       },
       "dependencies": {
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
-        },
         "node-fetch": {
           "version": "2.3.0",
           "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.3.0.tgz",
@@ -68,19 +100,35 @@
         }
       }
     },
+    "@octokit/rest": {
+      "version": "16.15.0",
+      "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-16.15.0.tgz",
+      "integrity": "sha512-Un+e7rgh38RtPOTe453pT/KPM/p2KZICimBmuZCd2wEo8PacDa4h6RqTPZs+f2DPazTTqdM7QU4LKlUjgiBwWw==",
+      "requires": {
+        "@octokit/request": "2.3.0",
+        "before-after-hook": "^1.2.0",
+        "btoa-lite": "^1.0.0",
+        "lodash.get": "^4.4.2",
+        "lodash.set": "^4.3.2",
+        "lodash.uniq": "^4.5.0",
+        "octokit-pagination-methods": "^1.1.0",
+        "universal-user-agent": "^2.0.0",
+        "url-template": "^2.0.8"
+      }
+    },
     "@octokit/webhooks": {
-      "version": "5.0.2",
-      "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-5.0.2.tgz",
-      "integrity": "sha512-htxI5cNiaEOlJbero6akw8bVZm3maN7LtCZbczxJQko3NvQqiROmzryE39+FnaoaHkQr6IAOx2JnPBZlkPHnVQ==",
+      "version": "5.3.2",
+      "resolved": "https://registry.npmjs.org/@octokit/webhooks/-/webhooks-5.3.2.tgz",
+      "integrity": "sha512-kZatFgkNldvU/Dv7A6YNA03yUy3Ual9g6sXs+oGqI+PgUGC6QudOMu8jfWkbmKXn+qrD2GfGBt5yClmS2aqKzw==",
       "requires": {
         "buffer-equal-constant-time": "^1.0.1",
         "debug": "^4.0.0"
       },
       "dependencies": {
         "debug": {
-          "version": "4.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz",
-          "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==",
+          "version": "4.1.1",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+          "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
           "requires": {
             "ms": "^2.1.1"
           }
@@ -94,7 +142,7 @@
     },
     "@types/supports-color": {
       "version": "5.3.0",
-      "resolved": "http://registry.npmjs.org/@types/supports-color/-/supports-color-5.3.0.tgz",
+      "resolved": "https://registry.npmjs.org/@types/supports-color/-/supports-color-5.3.0.tgz",
       "integrity": "sha512-WxwTXnHTIsk7srax1icjLgX+6w1MUAJbhyCpRP/45paEElsPDQUJZDgr1UpKuL2S3Tb+ZyX9MjWwmcSD4bUoOQ=="
     },
     "abab": {
@@ -180,14 +228,6 @@
       "integrity": "sha512-OtUw6JUTgxA2QoqqmrmQ7F2NYqiBPi/L2jqHyFtllhOUvXYQXf0Z1CYUinIfyT4bTCGmrA7gX9FvHA81uzCoVw==",
       "dev": true
     },
-    "agent-base": {
-      "version": "4.2.0",
-      "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.2.0.tgz",
-      "integrity": "sha512-c+R/U5X+2zz2+UCrCFv6odQzJdoqI+YecuhnAJLa1zYaMc13zPfwMwZrr91Pd1DYNo/yPRbiM4WVf9whgwFsIg==",
-      "requires": {
-        "es6-promisify": "^5.0.0"
-      }
-    },
     "ajv": {
       "version": "5.5.2",
       "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
@@ -1023,9 +1063,9 @@
       }
     },
     "before-after-hook": {
-      "version": "1.1.0",
-      "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-1.1.0.tgz",
-      "integrity": "sha512-VOMDtYPwLbIncTxNoSzRyvaMxtXmLWLUqr8k5AfC1BzLk34HvBXaQX8snOwQZ4c0aX8aSERqtJSiI9/m2u5kuA=="
+      "version": "1.3.2",
+      "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-1.3.2.tgz",
+      "integrity": "sha512-zyPgY5dgbf99c0uGUjhY4w+mxqEGxPKg9RQDl34VvrVh2bM31lFN+mwR1ZHepq/KA3VCPk1gwJZL6IIJqjLy2w=="
     },
     "binary-extensions": {
       "version": "1.12.0",
@@ -1066,9 +1106,9 @@
       }
     },
     "bottleneck": {
-      "version": "2.13.0",
-      "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.13.0.tgz",
-      "integrity": "sha512-9YmZ0aiKta2OAxTujKCS/INjGWCIGWK4Ff1nQpgHnR4CTjlk9jcnpaHOjPnMZPtqRXkqwKdtxZgvJ9udsXylaw=="
+      "version": "2.16.1",
+      "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.16.1.tgz",
+      "integrity": "sha512-OOHt4HXiMoXKUcQR/LBzwMYWCQxOU74c8zs6/VPCe6xO3kOAZBZqYKmrgsamVXa1wm9iztD1DAoV46KmGKLl5g=="
     },
     "boxen": {
       "version": "1.3.0",
@@ -1233,6 +1273,17 @@
       "requires": {
         "async": "1.5.2",
         "lru-cache": "4.0.0"
+      },
+      "dependencies": {
+        "lru-cache": {
+          "version": "4.0.0",
+          "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.0.tgz",
+          "integrity": "sha1-tcvwFVbBaWb+vlTO7A+03JDfbCg=",
+          "requires": {
+            "pseudomap": "^1.0.1",
+            "yallist": "^2.0.0"
+          }
+        }
       }
     },
     "caller-path": {
@@ -1551,6 +1602,11 @@
         }
       }
     },
+    "cluster-key-slot": {
+      "version": "1.0.12",
+      "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.0.12.tgz",
+      "integrity": "sha512-21O0kGmvED5OJ7ZTdqQ5lQQ+sjuez33R+d35jZKLwqUb5mqcPHUsxOSzj61+LHVtxGZd1kShbQM3MjB/gBJkVg=="
+    },
     "co": {
       "version": "4.6.0",
       "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
@@ -1600,8 +1656,7 @@
     "commander": {
       "version": "2.19.0",
       "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
-      "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
-      "dev": true
+      "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="
     },
     "component-emitter": {
       "version": "1.2.1",
@@ -1858,6 +1913,11 @@
       "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=",
       "dev": true
     },
+    "deepmerge": {
+      "version": "3.1.0",
+      "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-3.1.0.tgz",
+      "integrity": "sha512-/TnecbwXEdycfbsM2++O3eGiatEFHjjNciHEwJclM+T5Kd94qD1AP+2elP/Mq0L5b9VZJao5znR01Mz6eX8Seg=="
+    },
     "default-require-extensions": {
       "version": "1.0.0",
       "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-1.0.0.tgz",
@@ -2000,6 +2060,11 @@
       "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=",
       "dev": true
     },
+    "denque": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.0.tgz",
+      "integrity": "sha512-gh513ac7aiKrAgjiIBWZG0EASyDF9p4JMWwKA8YU5s9figrL5SRNEMT6FDynsegakuhWd1wVqTvqvqAoDxw7wQ=="
+    },
     "depd": {
       "version": "1.1.2",
       "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
@@ -2059,9 +2124,9 @@
       }
     },
     "dotenv": {
-      "version": "6.1.0",
-      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.1.0.tgz",
-      "integrity": "sha512-/veDn2ztgRlB7gKmE3i9f6CmDIyXAy6d5nBq+whO9SLX+Zs1sXEgFLPi+aSuWqUuusMfbi84fT8j34fs1HaYUw=="
+      "version": "6.2.0",
+      "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-6.2.0.tgz",
+      "integrity": "sha512-HygQCKUBSFl8wKQZBSemMywRWcEDNidvNbjGVyZu3nbZ8qq9ubiPoGLMdRDpfSrpkkm9BXYFkpKxxFX38o/76w=="
     },
     "dtrace-provider": {
       "version": "0.8.7",
@@ -2070,14 +2135,6 @@
       "optional": true,
       "requires": {
         "nan": "^2.10.0"
-      },
-      "dependencies": {
-        "nan": {
-          "version": "2.11.1",
-          "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
-          "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==",
-          "optional": true
-        }
       }
     },
     "duplexer3": {
@@ -2096,6 +2153,14 @@
         "safer-buffer": "^2.1.0"
       }
     },
+    "ecdsa-sig-formatter": {
+      "version": "1.0.10",
+      "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
+      "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
+      "requires": {
+        "safe-buffer": "^5.0.1"
+      }
+    },
     "ee-first": {
       "version": "1.1.1",
       "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
@@ -2147,19 +2212,6 @@
         "is-symbol": "^1.0.1"
       }
     },
-    "es6-promise": {
-      "version": "4.2.4",
-      "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.4.tgz",
-      "integrity": "sha512-/NdNZVJg+uZgtm9eS3O6lrOLYmQag2DjdEXuPaHlZ6RuVqgqaVZfgYCepEIKsLqwdQArOPtC3XzRLqGGfT8KQQ=="
-    },
-    "es6-promisify": {
-      "version": "5.0.0",
-      "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
-      "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
-      "requires": {
-        "es6-promise": "^4.0.3"
-      }
-    },
     "escape-html": {
       "version": "1.0.3",
       "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
@@ -2831,6 +2883,11 @@
         "write": "^0.2.1"
       }
     },
+    "flexbuffer": {
+      "version": "0.0.6",
+      "resolved": "https://registry.npmjs.org/flexbuffer/-/flexbuffer-0.0.6.tgz",
+      "integrity": "sha1-A5/fI/iCPkQMOPMnfm/vEXQhWzA="
+    },
     "for-in": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
@@ -3764,7 +3821,7 @@
     },
     "http-errors": {
       "version": "1.6.3",
-      "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+      "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
       "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
       "requires": {
         "depd": "~1.1.2",
@@ -3773,25 +3830,6 @@
         "statuses": ">= 1.4.0 < 2"
       }
     },
-    "http-proxy-agent": {
-      "version": "2.1.0",
-      "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-2.1.0.tgz",
-      "integrity": "sha512-qwHbBLV7WviBl0rQsOzH6o5lwyOIvwp/BdFnvVxXORldu5TmjFfjzBcWUWS5kWAZhmv+JtiDhSuQCp4sBfbIgg==",
-      "requires": {
-        "agent-base": "4",
-        "debug": "3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.1.0",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz",
-          "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==",
-          "requires": {
-            "ms": "2.0.0"
-          }
-        }
-      }
-    },
     "http-signature": {
       "version": "1.2.0",
       "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
@@ -3803,30 +3841,6 @@
         "sshpk": "^1.7.0"
       }
     },
-    "https-proxy-agent": {
-      "version": "2.2.1",
-      "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-2.2.1.tgz",
-      "integrity": "sha512-HPCTS1LW51bcyMYbxUIOO4HEOlQ1/1qRaFWcyxvwaqUS9TY88aoEuHUY33kuAh1YhVVaDQhLZsnPd+XNARWZlQ==",
-      "requires": {
-        "agent-base": "^4.1.0",
-        "debug": "^3.1.0"
-      },
-      "dependencies": {
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
-        }
-      }
-    },
     "iconv-lite": {
       "version": "0.4.19",
       "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz",
@@ -3976,6 +3990,38 @@
       "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=",
       "dev": true
     },
+    "ioredis": {
+      "version": "4.6.2",
+      "resolved": "https://registry.npmjs.org/ioredis/-/ioredis-4.6.2.tgz",
+      "integrity": "sha512-zlc/LeoeriHTXm5z3rakPcfRcUV9x+xr0E+7/L7KH0D5z7sI5ngEQWR2RUxnwFcxUcCkvrXMztRIdBP3DhqMAQ==",
+      "requires": {
+        "cluster-key-slot": "^1.0.6",
+        "debug": "^3.1.0",
+        "denque": "^1.1.0",
+        "flexbuffer": "0.0.6",
+        "lodash.defaults": "^4.2.0",
+        "lodash.flatten": "^4.4.0",
+        "redis-commands": "1.4.0",
+        "redis-errors": "^1.2.0",
+        "redis-parser": "^3.0.0",
+        "standard-as-callback": "^1.0.0"
+      },
+      "dependencies": {
+        "debug": {
+          "version": "3.2.6",
+          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+          "requires": {
+            "ms": "^2.1.1"
+          }
+        },
+        "ms": {
+          "version": "2.1.1",
+          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
+          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
+        }
+      }
+    },
     "ipaddr.js": {
       "version": "1.8.0",
       "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz",
@@ -3996,9 +4042,9 @@
       "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
     },
     "is-base64": {
-      "version": "0.0.5",
-      "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.0.5.tgz",
-      "integrity": "sha512-eRLie1GvKWp5Hab3x0uZXOvxrlw72elV2qEcvrNeoqNv6W30BjyvdiEqouaIrU3qh5KWRlxJp7iDLipA/hNOsA=="
+      "version": "0.1.0",
+      "resolved": "https://registry.npmjs.org/is-base64/-/is-base64-0.1.0.tgz",
+      "integrity": "sha512-WRRyllsGXJM7ZN7gPTCCQ/6wNPTRDwiWdPK66l5sJzcU/oOzcIcRRf0Rux8bkpox/1yjt0F6VJRsQOIG2qz5sg=="
     },
     "is-binary-path": {
       "version": "1.0.1",
@@ -4191,7 +4237,6 @@
       "version": "2.0.4",
       "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
       "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
-      "dev": true,
       "requires": {
         "isobject": "^3.0.1"
       },
@@ -4199,8 +4244,7 @@
         "isobject": {
           "version": "3.0.1",
           "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
-          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=",
-          "dev": true
+          "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8="
         }
       }
     },
@@ -5068,9 +5112,9 @@
       "dev": true
     },
     "jsonwebtoken": {
-      "version": "8.3.0",
-      "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.3.0.tgz",
-      "integrity": "sha512-oge/hvlmeJCH+iIz1DwcO7vKPkNGJHhgkspk8OH3VKlw+mbi42WtD4ig1+VXRln765vxptAv+xT26Fd3cteqag==",
+      "version": "8.4.0",
+      "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-8.4.0.tgz",
+      "integrity": "sha512-coyXjRTCy0pw5WYBpMvWOMN+Kjaik2MwTUIq9cna/W7NpO9E+iYbumZONAz3hcr+tXFJECoQVrtmIoC3Oz0gvg==",
       "requires": {
         "jws": "^3.1.5",
         "lodash.includes": "^4.3.0",
@@ -5112,31 +5156,21 @@
       }
     },
     "jwa": {
-      "version": "1.1.6",
-      "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.1.6.tgz",
-      "integrity": "sha512-tBO/cf++BUsJkYql/kBbJroKOgHWEigTKBAjjBEmrMGYd1QMBC74Hr4Wo2zCZw6ZrVhlJPvoMrkcOnlWR/DJfw==",
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.2.0.tgz",
+      "integrity": "sha512-Grku9ZST5NNQ3hqNUodSkDfEBqAmGA1R8yiyPHOnLzEKI0GaCQC/XhFmsheXYuXzFQJdILbh+lYBiliqG5R/Vg==",
       "requires": {
         "buffer-equal-constant-time": "1.0.1",
         "ecdsa-sig-formatter": "1.0.10",
         "safe-buffer": "^5.0.1"
-      },
-      "dependencies": {
-        "ecdsa-sig-formatter": {
-          "version": "1.0.10",
-          "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.10.tgz",
-          "integrity": "sha1-HFlQAPBKiJffuFAAiSoPTDOvhsM=",
-          "requires": {
-            "safe-buffer": "^5.0.1"
-          }
-        }
       }
     },
     "jws": {
-      "version": "3.1.5",
-      "resolved": "https://registry.npmjs.org/jws/-/jws-3.1.5.tgz",
-      "integrity": "sha512-GsCSexFADNQUr8T5HPJvayTjvPIfoyJPtLQBwn5a4WZQchcrPMPMAWcC1AzJVRDKyD6ZPROPAxgv6rfHViO4uQ==",
+      "version": "3.2.1",
+      "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.1.tgz",
+      "integrity": "sha512-bGA2omSrFUkd72dhh05bIAN832znP4wOU3lfuXtRBuGTbsmNmDXMQg28f0Vsxaxgk4myF5YkKQpz6qeRpMgX9g==",
       "requires": {
-        "jwa": "^1.1.5",
+        "jwa": "^1.2.0",
         "safe-buffer": "^5.0.1"
       }
     },
@@ -5218,7 +5252,8 @@
     "lodash": {
       "version": "4.17.11",
       "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
-      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
+      "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==",
+      "dev": true
     },
     "lodash.cond": {
       "version": "4.5.2",
@@ -5232,6 +5267,21 @@
       "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168=",
       "dev": true
     },
+    "lodash.defaults": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
+      "integrity": "sha1-0JF4cW/+pN3p5ft7N/bwgCJ0WAw="
+    },
+    "lodash.flatten": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz",
+      "integrity": "sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8="
+    },
+    "lodash.get": {
+      "version": "4.4.2",
+      "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz",
+      "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk="
+    },
     "lodash.includes": {
       "version": "4.3.0",
       "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
@@ -5272,12 +5322,22 @@
       "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
       "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w="
     },
+    "lodash.set": {
+      "version": "4.3.2",
+      "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz",
+      "integrity": "sha1-2HV7HagH3eJIFrDWqEvqGnYjCyM="
+    },
     "lodash.sortby": {
       "version": "4.7.0",
       "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz",
       "integrity": "sha1-7dFMgk4sycHgsKG0K7UhBRakJDg=",
       "dev": true
     },
+    "lodash.uniq": {
+      "version": "4.5.0",
+      "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+      "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M="
+    },
     "longest": {
       "version": "1.0.1",
       "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
@@ -5299,12 +5359,18 @@
       "dev": true
     },
     "lru-cache": {
-      "version": "4.0.0",
-      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.0.0.tgz",
-      "integrity": "sha1-tcvwFVbBaWb+vlTO7A+03JDfbCg=",
+      "version": "5.1.1",
+      "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+      "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
       "requires": {
-        "pseudomap": "^1.0.1",
-        "yallist": "^2.0.0"
+        "yallist": "^3.0.2"
+      },
+      "dependencies": {
+        "yallist": {
+          "version": "3.0.3",
+          "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.3.tgz",
+          "integrity": "sha512-S+Zk8DEWE6oKpV+vI3qWkaK+jSbIK86pCwe2IF/xwIpQ8jEuxpw9NyaGjmp9+BoJv5FV2piqCDcoCtStppiq2A=="
+        }
       }
     },
     "macos-release": {
@@ -5498,9 +5564,9 @@
       }
     },
     "moment": {
-      "version": "2.22.2",
-      "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz",
-      "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=",
+      "version": "2.24.0",
+      "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz",
+      "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==",
       "optional": true
     },
     "morgan": {
@@ -5542,7 +5608,6 @@
       "version": "2.11.1",
       "resolved": "https://registry.npmjs.org/nan/-/nan-2.11.1.tgz",
       "integrity": "sha512-iji6k87OSXa0CcrLl9z+ZiYSuR2o+c0bGuNmXdrhTQTakxytAFsC56SArGYoiHlJlFoHSnvmhpceZJaXkVuOtA==",
-      "dev": true,
       "optional": true
     },
     "nanomatch": {
@@ -5592,7 +5657,7 @@
     },
     "ncp": {
       "version": "2.0.0",
-      "resolved": "http://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
+      "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz",
       "integrity": "sha1-GVoh1sRuNh0vsSgbo4uR6d9727M=",
       "optional": true
     },
@@ -5822,6 +5887,11 @@
         }
       }
     },
+    "octokit-pagination-methods": {
+      "version": "1.1.0",
+      "resolved": "https://registry.npmjs.org/octokit-pagination-methods/-/octokit-pagination-methods-1.1.0.tgz",
+      "integrity": "sha512-fZ4qZdQ2nxJvtcasX7Ghl+WlWS/d9IgnBIwFZXVNNZUmzpno91SX5bc5vuxiuKoCtK78XxGGNuSCrDC7xYB3OQ=="
+    },
     "on-finished": {
       "version": "2.3.0",
       "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
@@ -6218,85 +6288,53 @@
       "dev": true
     },
     "probot": {
-      "version": "7.3.1",
-      "resolved": "https://registry.npmjs.org/probot/-/probot-7.3.1.tgz",
-      "integrity": "sha512-zzavBZAe1kSk3dJnhHOTmd+x1uxktuKe67KKKTNiqO+Cmov38Gsb1FCzMtjoxvatvGfVvpOg9tJb+13cQAdgCA==",
-      "requires": {
-        "@octokit/rest": "^15.13.1",
-        "@octokit/webhooks": "^5.0.2",
+      "version": "8.0.0-beta.6",
+      "resolved": "https://registry.npmjs.org/probot/-/probot-8.0.0-beta.6.tgz",
+      "integrity": "sha512-Viz4Aj7VyH2tvEdNYQTPuTT/sVkqPoAC5kYa6X3X3cwThVI+tjKHaJDSC5YWukRmcrFfh7u7mLu8iX1IkHnBaQ==",
+      "requires": {
+        "@octokit/app": "^2.1.0",
+        "@octokit/graphql": "2.0.1",
+        "@octokit/plugin-enterprise-compatibility": "^1.0.0",
+        "@octokit/plugin-retry": "^2.1.1",
+        "@octokit/plugin-throttling": "^2.3.0",
+        "@octokit/rest": "^16.13.3",
+        "@octokit/webhooks": "^5.3.1",
         "@types/supports-color": "^5.3.0",
-        "bottleneck": "^2.8.0",
+        "bottleneck": "^2.15.3",
         "bunyan": "^1.8.12",
         "bunyan-format": "^0.2.1",
         "bunyan-sentry-stream": "^1.1.0",
         "cache-manager": "^2.4.0",
         "commander": "^2.19.0",
-        "dotenv": "~6.1.0",
+        "dotenv": "~6.2.0",
         "express": "^4.16.2",
         "express-async-errors": "^3.0.0",
         "hbs": "^4.0.1",
-        "is-base64": "0.0.5",
+        "ioredis": "^4.5.1",
+        "is-base64": "0.1.0",
         "js-yaml": "^3.9.1",
         "jsonwebtoken": "^8.1.0",
+        "octokit-pagination-methods": "1.1.0",
         "pkg-conf": "^2.0.0",
         "promise-events": "^0.1.3",
         "qs": "^6.5.2",
         "raven": "^2.4.2",
         "resolve": "^1.4.0",
         "semver": "^5.5.0",
-        "supports-color": "^5.5.0",
+        "supports-color": "^6.0.0",
         "update-dotenv": "^1.1.0",
         "uuid": "^3.2.1"
       },
       "dependencies": {
-        "@octokit/rest": {
-          "version": "15.16.1",
-          "resolved": "https://registry.npmjs.org/@octokit/rest/-/rest-15.16.1.tgz",
-          "integrity": "sha512-86RGoibm8AJ3ZBlM0NdMI932wEZ/bdo2eEppHtliEYwJT9hsy5qt+i9HA+T8CC90r4atoFQDrY7mDLBcAjp9ow==",
-          "requires": {
-            "before-after-hook": "^1.1.0",
-            "btoa-lite": "^1.0.0",
-            "debug": "^3.1.0",
-            "http-proxy-agent": "^2.1.0",
-            "https-proxy-agent": "^2.2.0",
-            "lodash": "^4.17.4",
-            "node-fetch": "^2.1.1",
-            "universal-user-agent": "^2.0.0",
-            "url-template": "^2.0.8"
-          }
-        },
-        "commander": {
-          "version": "2.19.0",
-          "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
-          "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg=="
-        },
-        "debug": {
-          "version": "3.2.6",
-          "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
-          "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
-          "requires": {
-            "ms": "^2.1.1"
-          }
-        },
         "has-flag": {
           "version": "3.0.0",
           "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
           "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
         },
-        "ms": {
-          "version": "2.1.1",
-          "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
-          "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
-        },
-        "node-fetch": {
-          "version": "2.2.1",
-          "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.2.1.tgz",
-          "integrity": "sha512-ObXBpNCD3A/vYQiQtEWl7DuqjAXjfptYFuGHLdPl5U19/6kJuZV+8uMHLrkj3wJrJoyfg4nhgyFixZdaZoAiEQ=="
-        },
         "qs": {
-          "version": "6.5.2",
-          "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
-          "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
+          "version": "6.6.0",
+          "resolved": "https://registry.npmjs.org/qs/-/qs-6.6.0.tgz",
+          "integrity": "sha512-KIJqT9jQJDQx5h5uAVPimw6yVg2SekOKu959OCtktD3FjzbpvaPr8i4zzg07DOMz+igA4W/aNM7OV8H37pFYfA=="
         },
         "semver": {
           "version": "5.6.0",
@@ -6304,9 +6342,9 @@
           "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg=="
         },
         "supports-color": {
-          "version": "5.5.0",
-          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
-          "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+          "version": "6.1.0",
+          "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
+          "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
           "requires": {
             "has-flag": "^3.0.0"
           }
@@ -6856,6 +6894,24 @@
         "util.promisify": "^1.0.0"
       }
     },
+    "redis-commands": {
+      "version": "1.4.0",
+      "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.4.0.tgz",
+      "integrity": "sha512-cu8EF+MtkwI4DLIT0x9P8qNTLFhQD4jLfxLR0cCNkeGzs87FN6879JOJwNQR/1zD7aSYNbU0hgsV9zGY71Itvw=="
+    },
+    "redis-errors": {
+      "version": "1.2.0",
+      "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
+      "integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
+    },
+    "redis-parser": {
+      "version": "3.0.0",
+      "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
+      "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
+      "requires": {
+        "redis-errors": "^1.0.0"
+      }
+    },
     "regenerator-runtime": {
       "version": "0.11.1",
       "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
@@ -7862,6 +7918,11 @@
         "standard-engine": "~8.0.0"
       }
     },
+    "standard-as-callback": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-1.0.2.tgz",
+      "integrity": "sha512-1Qrah+2Vmj8DiftcXR9gfUe/gFmOukdnxF5v7G/apCZbLtjh3rjss8Eu6Qlprm6zerrl+qDmvm7KXpJedqpoAQ=="
+    },
     "standard-engine": {
       "version": "8.0.0",
       "resolved": "https://registry.npmjs.org/standard-engine/-/standard-engine-8.0.0.tgz",
diff --git a/package.json b/package.json
index 3f03663..c07d5a8 100644
--- a/package.json
+++ b/package.json
@@ -36,11 +36,11 @@
     ]
   },
   "dependencies": {
-    "@octokit/rest": "^15.18.0",
+    "@octokit/rest": "^16.15.0",
     "hbs": "^4.0.1",
     "joi": "^14.3.0",
     "parse-diff": "^0.5.1",
-    "probot": "^7.3.1"
+    "probot": "^8.0.0-beta.6"
   },
   "devDependencies": {
     "chalk": "^2.4.1",


Test patch:
diff --git a/tests/helpers.js b/tests/helpers.js
index 0dce1dd..f39c4b6 100644
--- a/tests/helpers.js
+++ b/tests/helpers.js
@@ -36,25 +36,25 @@ exports.gimmeApp = () => {
     issues: {
       create: jest.fn().mockName('issues.create'),
       createLabel: jest.fn().mockName('issues.createLabel'),
-      edit: jest.fn().mockName('issues.edit'),
+      update: jest.fn().mockName('issues.update'),
       createComment: jest.fn().mockName('issues.createComment'),
-      getComments: jest.fn(() => Promise.resolve({ data: [] })).mockName('issues.getComments')
+      listComments: jest.fn(() => Promise.resolve({ data: [] })).mockName('issues.listComments')
     },
     search: {
-      issues: jest.fn(() => Promise.resolve({ data: { total_count: 0, items: [] } })).mockName('search.issues')
+      issuesAndPullRequests: jest.fn(() => Promise.resolve({ data: { total_count: 0, items: [] } })).mockName('search.issuesAndPullRequests')
     },
-    gitdata: {
-      getCommit: jest.fn(() => Promise.resolve({ data: { parents: [1] } })).mockName('gitdata.getCommit')
+    git: {
+      getCommit: jest.fn(() => Promise.resolve({ data: { parents: [1] } })).mockName('git.getCommit')
     },
     repos: {
       // Response for getting content from '.github/todo.yml'
-      getContent: jest.fn(() => {
+      getContents: jest.fn(() => {
         throw { code: 404 } // eslint-disable-line
-      }).mockName('repos.getContent'),
+      }).mockName('repos.getContents'),
       getCommit: jest.fn(() => loadDiff('basic')).mockName('repos.getCommit')
     },
-    pullRequests: {
-      get: jest.fn(() => loadDiff('basic')).mockName('pullRequests.get')
+    pulls: {
+      get: jest.fn(() => loadDiff('basic')).mockName('pulls.get')
     },
     hook: {
       before: jest.fn()
diff --git a/tests/issue-rename-handler.test.js b/tests/issue-rename-handler.test.js
index 13b0d77..8b21429 100644
--- a/tests/issue-rename-handler.test.js
+++ b/tests/issue-rename-handler.test.js
@@ -11,7 +11,7 @@ describe('issue-rename-handler', () => {
 
     github = {
       issues: {
-        edit: jest.fn(),
+        update: jest.fn(),
         createComment: jest.fn()
       }
     }
@@ -22,14 +22,14 @@ describe('issue-rename-handler', () => {
 
   it('un-edits the issue title', async () => {
     await app.receive(event)
-    expect(github.issues.edit.mock.calls[0][0]).toMatchSnapshot()
+    expect(github.issues.update.mock.calls[0][0]).toMatchSnapshot()
     expect(github.issues.createComment.mock.calls[0][0]).toMatchSnapshot()
   })
 
   it('only acts if the title is edited', async () => {
     event.payload.changes = {}
     await app.receive(event)
-    expect(github.issues.edit).not.toHaveBeenCalled()
+    expect(github.issues.update).not.toHaveBeenCalled()
     expect(github.issues.createComment).not.toHaveBeenCalled()
   })
 })
diff --git a/tests/pull-request-handler.test.js b/tests/pull-request-handler.test.js
index f7f8085..d38da5b 100644
--- a/tests/pull-request-handler.test.js
+++ b/tests/pull-request-handler.test.js
@@ -18,19 +18,19 @@ describe('pull-request-handler', () => {
   })
 
   it('comments on a pull request and mentions the assigned user', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignString'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignString'))
     await app.receive(event)
     expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
   })
 
   it('comments on a pull request and mentions the assigned users', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignArr'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignArr'))
     await app.receive(event)
     expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
   })
 
   it('does not create duplicate comments', async () => {
-    github.issues.getComments.mockReturnValueOnce(Promise.resolve({ data: [{
+    github.issues.listComments.mockReturnValueOnce(Promise.resolve({ data: [{
       body: '## I am an example title'
     }] }))
 
@@ -39,32 +39,32 @@ describe('pull-request-handler', () => {
   })
 
   it('creates many (5) comments', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('many'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('many'))
     await app.receive(event)
     expect(github.issues.createComment).toHaveBeenCalledTimes(5)
   })
 
   it('ignores changes to the config file', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('config'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('config'))
     await app.receive(event)
     expect(github.issues.createComment).not.toHaveBeenCalled()
   })
 
   it('ignores changes to the bin directory', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('bin'))
-    github.repos.getContent.mockReturnValueOnce(loadConfig('excludeBin'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('bin'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('excludeBin'))
     await app.receive(event)
     expect(github.issues.createComment).not.toHaveBeenCalled()
   })
 
   it('works with a string as the keyword config', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('keywordsString'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('keywordsString'))
     await app.receive(event)
     expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
   })
 
   it('creates a comment with a body line', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('body'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('body'))
     await app.receive(event)
     expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
   })
diff --git a/tests/pull-request-merge-handler.test.js b/tests/pull-request-merge-handler.test.js
index 1f1fa41..571ba1a 100644
--- a/tests/pull-request-merge-handler.test.js
+++ b/tests/pull-request-merge-handler.test.js
@@ -30,38 +30,38 @@ describe('pull-request-merged-handler', () => {
   })
 
   it('creates an issue with a truncated title', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('long-title'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('long-title'))
     await app.receive(event)
     expect(github.issues.create).toHaveBeenCalledTimes(1)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('creates an issue without assigning anyone', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignFalse'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignFalse'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('creates an issue and assigns the configured user', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignString'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignString'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('creates an issue and assigns the configured users', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignArr'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignArr'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('does not create any issues if no todos are found', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('none'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('none'))
     await app.receive(event)
     expect(github.issues.create).not.toHaveBeenCalled()
   })
 
   it('does not create an issue that already exists', async () => {
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'I am an example title', state: 'open' }] }
     }))
     await app.receive(event)
@@ -69,48 +69,48 @@ describe('pull-request-merged-handler', () => {
   })
 
   it('creates many (5) issues', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('many'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('many'))
     await app.receive(event)
     expect(github.issues.create).toHaveBeenCalledTimes(5)
   })
 
   it('ignores changes to the config file', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('config'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('config'))
     await app.receive(event)
     expect(github.issues.create).not.toHaveBeenCalled()
   })
 
   it('ignores changes to the bin directory', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('bin'))
-    github.repos.getContent.mockReturnValueOnce(loadConfig('excludeBin'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('bin'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('excludeBin'))
     await app.receive(event)
     expect(github.issues.createComment).not.toHaveBeenCalled()
   })
 
   it('creates an issue with a body line', async () => {
-    github.pullRequests.get.mockReturnValueOnce(loadDiff('body'))
+    github.pulls.get.mockReturnValueOnce(loadDiff('body'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('reopens a closed issue', async () => {
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'I am an example title', state: 'closed' }] }
     }))
     await app.receive(event)
-    expect(github.issues.edit).toHaveBeenCalledTimes(1)
+    expect(github.issues.update).toHaveBeenCalledTimes(1)
     expect(github.issues.createComment).toHaveBeenCalledTimes(1)
     expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
     expect(github.issues.create).not.toHaveBeenCalled()
   })
 
   it('respects the reopenClosed config', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('reopenClosedFalse'))
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.repos.getContents.mockReturnValueOnce(loadConfig('reopenClosedFalse'))
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'I am an example title', state: 'closed' }] }
     }))
     await app.receive(event)
-    expect(github.issues.edit).not.toHaveBeenCalled()
+    expect(github.issues.update).not.toHaveBeenCalled()
     expect(github.issues.createComment).not.toHaveBeenCalled()
     expect(github.issues.create).not.toHaveBeenCalled()
   })
diff --git a/tests/push-handler.test.js b/tests/push-handler.test.js
index 140b46f..76af291 100644
--- a/tests/push-handler.test.js
+++ b/tests/push-handler.test.js
@@ -25,19 +25,19 @@ describe('push-handler', () => {
   })
 
   it('creates an issue without assigning anyone', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignFalse'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignFalse'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('creates an issue and assigns the configured user', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignString'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignString'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('creates an issue and assigns the configured users', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('autoAssignArr'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('autoAssignArr'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
@@ -54,7 +54,7 @@ describe('push-handler', () => {
   })
 
   it('does not create an issue that already exists', async () => {
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'I am an example title', state: 'open' }] }
     }))
     await app.receive(event)
@@ -62,7 +62,7 @@ describe('push-handler', () => {
   })
 
   it('creates an issue if the search does not have an issue with the correct title', async () => {
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'Not found', state: 'open' }] }
     }))
     await app.receive(event)
@@ -84,7 +84,7 @@ describe('push-handler', () => {
 
   it('ignores changes to the bin directory', async () => {
     github.repos.getCommit.mockReturnValueOnce(loadDiff('bin'))
-    github.repos.getContent.mockReturnValueOnce(loadConfig('excludeBin'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('excludeBin'))
     await app.receive(event)
     expect(github.issues.create).not.toHaveBeenCalled()
   })
@@ -96,7 +96,7 @@ describe('push-handler', () => {
   })
 
   it('ignores merge commits', async () => {
-    github.gitdata.getCommit.mockReturnValueOnce(Promise.resolve({
+    github.git.getCommit.mockReturnValueOnce(Promise.resolve({
       data: { parents: [1, 2] }
     }))
     await app.receive(event)
@@ -111,35 +111,35 @@ describe('push-handler', () => {
 
   it('creates an issue with a body line with one body keyword', async () => {
     github.repos.getCommit.mockReturnValueOnce(loadDiff('body'))
-    github.repos.getContent.mockReturnValueOnce(loadConfig('bodyString'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('bodyString'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })
 
   it('reopens a closed issue', async () => {
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'I am an example title', state: 'closed' }] }
     }))
     await app.receive(event)
-    expect(github.issues.edit).toHaveBeenCalledTimes(1)
+    expect(github.issues.update).toHaveBeenCalledTimes(1)
     expect(github.issues.createComment).toHaveBeenCalledTimes(1)
     expect(github.issues.createComment.mock.calls[0]).toMatchSnapshot()
     expect(github.issues.create).not.toHaveBeenCalled()
   })
 
   it('respects the reopenClosed config', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('reopenClosedFalse'))
-    github.search.issues.mockReturnValueOnce(Promise.resolve({
+    github.repos.getContents.mockReturnValueOnce(loadConfig('reopenClosedFalse'))
+    github.search.issuesAndPullRequests.mockReturnValueOnce(Promise.resolve({
       data: { total_count: 1, items: [{ title: 'I am an example title', state: 'closed' }] }
     }))
     await app.receive(event)
-    expect(github.issues.edit).not.toHaveBeenCalled()
+    expect(github.issues.update).not.toHaveBeenCalled()
     expect(github.issues.createComment).not.toHaveBeenCalled()
     expect(github.issues.create).not.toHaveBeenCalled()
   })
 
   it('does not show the blob if blobLines is false', async () => {
-    github.repos.getContent.mockReturnValueOnce(loadConfig('blobLinesFalse'))
+    github.repos.getContents.mockReturnValueOnce(loadConfig('blobLinesFalse'))
     await app.receive(event)
     expect(github.issues.create.mock.calls[0]).toMatchSnapshot()
   })