From cf1766b3e0e0dd11d7da5b893b77ed2ab3f2aaba Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@keylocation.sg>
Date: Sun, 27 Aug 2017 14:49:23 +0200
Subject: [PATCH] fix: always check github retries count (#745)

---
 lib/api/gh-got-retry.js | 51 ++++++++++++++++++++++++++---------------
 test/api/github.spec.js | 21 +++++++++++++++++
 2 files changed, 54 insertions(+), 18 deletions(-)

diff --git a/lib/api/gh-got-retry.js b/lib/api/gh-got-retry.js
index 6269246cab..ee3bf0fdd5 100644
--- a/lib/api/gh-got-retry.js
+++ b/lib/api/gh-got-retry.js
@@ -12,26 +12,41 @@ async function ghGotRetry(path, opts, retries = 5) {
     const res = await ghGot(path, opts);
     return res;
   } catch (err) {
-    if (err.statusCode >= 500 && err.statusCode < 600 && retries > 0) {
-      logger.debug(`Retrying statusCode ${err.statusCode}`);
-      // istanbul ignore if
-      if (process.env.NODE_ENV !== 'test') {
-        await sleep(5000 / retries);
+    if (retries > 0) {
+      if (
+        err.statusCode === 401 &&
+        err.message &&
+        err.message.indexOf('Bad credentials') === 0
+      ) {
+        logger.warn(`Retrying bad credentials once`);
+        // istanbul ignore if
+        if (process.env.NODE_ENV !== 'test') {
+          await sleep(180000 / (retries * retries));
+        }
+        return ghGotRetry(path, opts, 0);
       }
-      return ghGotRetry(path, opts, retries - 1);
-    }
-    if (
-      err.statusCode === 403 &&
-      err.message &&
-      err.message.indexOf('You have triggered an abuse detection mechanism') ===
-        0
-    ) {
-      logger.debug(`Retrying abuse detection trigger`);
-      // istanbul ignore if
-      if (process.env.NODE_ENV !== 'test') {
-        await sleep(180000 / (retries * retries));
+      if (
+        err.statusCode === 403 &&
+        err.message &&
+        err.message.indexOf(
+          'You have triggered an abuse detection mechanism'
+        ) === 0
+      ) {
+        logger.warn(`Retrying abuse detection trigger`);
+        // istanbul ignore if
+        if (process.env.NODE_ENV !== 'test') {
+          await sleep(180000 / (retries * retries));
+        }
+        return ghGotRetry(path, opts, retries - 1);
+      }
+      if (err.statusCode >= 500 && err.statusCode < 600) {
+        logger.info(`Retrying statusCode ${err.statusCode}`);
+        // istanbul ignore if
+        if (process.env.NODE_ENV !== 'test') {
+          await sleep(5000 / retries);
+        }
+        return ghGotRetry(path, opts, retries - 1);
       }
-      return ghGotRetry(path, opts, retries - 1);
     }
     throw err;
   }
diff --git a/test/api/github.spec.js b/test/api/github.spec.js
index 58d1d40ae9..098ab99356 100644
--- a/test/api/github.spec.js
+++ b/test/api/github.spec.js
@@ -95,6 +95,27 @@ describe('api/github', () => {
       }
       expect(err.statusCode).toBe(404);
     });
+    it('should retry 401 only once', async () => {
+      ghGot.mockImplementationOnce(() =>
+        Promise.reject({
+          statusCode: 401,
+          message: 'Bad credentials',
+        })
+      );
+      ghGot.mockImplementationOnce(() =>
+        Promise.reject({
+          statusCode: 401,
+          message: 'Bad credentials',
+        })
+      );
+      let err;
+      try {
+        await github.getInstallations('sometoken');
+      } catch (e) {
+        err = e;
+      }
+      expect(err.statusCode).toBe(401);
+    });
     it('should give up after 5 retries', async () => {
       ghGot.mockImplementationOnce(() =>
         Promise.reject({
-- 
GitLab