From b498c52e012a66271939d5586f9e868d84a22d0f Mon Sep 17 00:00:00 2001
From: Rhys Arkins <rhys@keylocation.sg>
Date: Wed, 11 Jan 2017 13:19:59 +0100
Subject: [PATCH] Large refactor of config and helpers

---
 .gitignore                 |   2 +-
 src/helpers/config.js      | 112 ++++++++++++++++++-------------------
 src/helpers/github.js      |  53 +++++++++---------
 src/helpers/npm.js         |  91 +++++++++++++-----------------
 src/helpers/packageJson.js |   4 +-
 src/index.js               |  39 +++++++------
 6 files changed, 141 insertions(+), 160 deletions(-)

diff --git a/.gitignore b/.gitignore
index 238be4fa4f..0b23a410a0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
 /node_modules
-/src/config.js
+/config.js
 /npm-debug.log
diff --git a/src/helpers/config.js b/src/helpers/config.js
index f96a047c44..30f5148dc3 100644
--- a/src/helpers/config.js
+++ b/src/helpers/config.js
@@ -7,68 +7,66 @@ const logger = new (winston.Logger)({
   ],
 });
 
-module.exports = {
+module.exports = function init() {
   // This function reads in all configs and merges them
-  init(argv) {
-    /* eslint-disable global-require */
-    const defaultConfig = require('../defaults');
-    let customConfig = {};
-    try {
-      customConfig = require('../config');
-    } catch (err) {
-      // Do nothing
+  /* eslint-disable global-require */
+  const defaultConfig = require('../defaults');
+  let customConfig = {};
+  try {
+    customConfig = require('../../config');
+  } catch (err) {
+    // Do nothing
+  }
+  /* eslint-enable global-require */
+  const cliConfig = {};
+  if (process.env.LOG_LEVEL) {
+    cliConfig.logLevel = process.env.LOG_LEVEL;
+  }
+  if (process.env.RENOVATE_TOKEN) {
+    cliConfig.token = process.env.RENOVATE_TOKEN;
+  }
+  // Check if repository name and package file are provided via CLI
+  const repoName = process.argv[2];
+  const packageFile = process.argv[3] || 'package.json';
+  if (repoName) {
+    cliConfig.repositories = [
+      {
+        name: repoName,
+        packageFiles: [packageFile],
+      },
+    ];
+  }
+  const config = Object.assign(defaultConfig, customConfig, cliConfig);
+  // First, convert any strings to objects
+  config.repositories.forEach((repo, index) => {
+    if (typeof repo === 'string') {
+      config.repositories[index] = { name: repo };
     }
-    /* eslint-enable global-require */
-    const cliConfig = {};
-    if (process.env.LOG_LEVEL) {
-      cliConfig.logLevel = process.env.LOG_LEVEL;
+  });
+  // Add 'package.json' if missing
+  config.repositories.forEach((repo, index) => {
+    if (!repo.packageFiles || !repo.packageFiles.length) {
+      config.repositories[index].packageFiles = ['package.json'];
     }
-    if (process.env.RENOVATE_TOKEN) {
-      cliConfig.token = process.env.RENOVATE_TOKEN;
-    }
-    // Check if repository name and package file are provided via CLI
-    const repoName = argv[2];
-    const packageFile = argv[3] || 'package.json';
-    if (repoName) {
-      cliConfig.repositories = [
-        {
-          name: repoName,
-          packageFiles: [packageFile],
-        },
-      ];
-    }
-    const config = Object.assign(defaultConfig, customConfig, cliConfig);
-    // First, convert any strings to objects
-    config.repositories.forEach((repo, index) => {
-      if (typeof repo === 'string') {
-        config.repositories[index] = { name: repo };
-      }
-    });
-    // Add 'package.json' if missing
-    config.repositories.forEach((repo, index) => {
-      if (!repo.packageFiles || !repo.packageFiles.length) {
-        config.repositories[index].packageFiles = ['package.json'];
-      }
-    });
+  });
 
 
-    // Winston log level can be controlled via config or env
-    if (config.logLevel) {
-      logger.level = config.logLevel;
-    }
-    logger.verbose(config);
-    config.logger = logger;
+  // Winston log level can be controlled via config or env
+  if (config.logLevel) {
+    logger.level = config.logLevel;
+  }
+  logger.verbose(config);
+  config.logger = logger;
 
-    // token must be defined
-    if (typeof config.token === 'undefined') {
-      logger.error('Error: A GitHub token must be configured');
-      process.exit(1);
-    }
-    // We also need a repository
-    if (!config.repositories || config.repositories.length === 0) {
-      logger.error('Error: At least one repository must be configured');
-    }
+  // token must be defined
+  if (typeof config.token === 'undefined') {
+    logger.error('Error: A GitHub token must be configured');
+    process.exit(1);
+  }
+  // We also need a repository
+  if (!config.repositories || config.repositories.length === 0) {
+    logger.error('Error: At least one repository must be configured');
+  }
 
-    return config;
-  },
+  return config;
 };
diff --git a/src/helpers/github.js b/src/helpers/github.js
index f11fd6312e..950a9bbbcf 100644
--- a/src/helpers/github.js
+++ b/src/helpers/github.js
@@ -1,41 +1,47 @@
 const ghGot = require('gh-got');
 
-let config = {};
+const config = {};
 let logger = null;
 
-module.exports = {
-  init,
+module.exports = function github(setLogger) {
+  logger = setLogger;
+  this.initRepo = initRepo;
   // Package File
-  getPackageFile,
-  getPackageFileContents,
-  writePackageFile,
+  this.getPackageFile = getPackageFile;
+  this.getPackageFileContents = getPackageFileContents;
+  this.writePackageFile = writePackageFile;
   // Branch
-  createBranch,
+  this.createBranch = createBranch;
   // PR
-  checkForClosedPr,
-  createPr,
-  getPr,
-  updatePr,
+  this.checkForClosedPr = checkForClosedPr;
+  this.createPr = createPr;
+  this.getPr = getPr;
+  this.updatePr = updatePr;
+  return this;
 };
 
 // Initialize GitHub by getting base branch and SHA
-function init(setConfig, repoName, packageFile) {
-  config = setConfig;
-  logger = config.logger;
+function initRepo(token, repoName) {
+  config.token = token;
   config.repoName = repoName;
-  config.packageFile = packageFile;
+
+  return getRepo()
+  .then(processRepo)
+  .catch((err) => {
+    logger.error(`GitHub init error: ${err}`);
+    throw err;
+  });
 
   function getRepo() {
+    logger.debug(`Getting repo ${repoName}`);
     return ghGot(`repos/${config.repoName}`, { token: config.token })
     .then(res => res.body);
   }
 
   function processRepo(repo) {
+    logger.debug(`Processing repo ${repoName}`);
     config.owner = repo.owner.login;
     config.defaultBranch = repo.default_branch;
-  }
-
-  function getRepoSHA() {
     return ghGot(`repos/${config.repoName}/git/refs/head`, {
       token: config.token,
     }).then((res) => {
@@ -50,14 +56,6 @@ function init(setConfig, repoName, packageFile) {
       return Promise.resolve();
     });
   }
-
-  return getRepo()
-  .then(processRepo)
-  .then(getRepoSHA)
-  .catch((err) => {
-    logger.error(`GitHub init error: ${err}`);
-    throw err;
-  });
 }
 
 // Package File
@@ -65,7 +63,8 @@ function getPackageFile(branchName) {
   return getFile(config.packageFile, branchName);
 }
 
-function getPackageFileContents() {
+function getPackageFileContents(packageFile) {
+  config.packageFile = packageFile;
   return getFileContents(config.packageFile);
 }
 
diff --git a/src/helpers/npm.js b/src/helpers/npm.js
index ff32c067f0..0249f91866 100644
--- a/src/helpers/npm.js
+++ b/src/helpers/npm.js
@@ -2,65 +2,50 @@ const got = require('got');
 const semver = require('semver');
 const stable = require('semver-stable');
 
-let config = {};
 let logger = null;
 
-module.exports = {
-  init(setConfig) {
-    config = setConfig;
-    logger = config.logger;
-  },
-  getDependencies(packageContents) {
-    const allDependencies = [];
-    const dependencyTypes = ['dependencies', 'devDependencies'];
-    dependencyTypes.forEach((depType) => {
-      Object.keys(packageContents[depType]).forEach((depName) => {
-        allDependencies.push({
-          depType,
-          depName,
-          currentVersion: packageContents[depType][depName],
-        });
-      });
-    });
-    return allDependencies;
-  },
-  getAllDependencyUpgrades(packageContents) {
-    const allDependencyChecks = [];
-    const allDependencyUpgrades = [];
-    const dependencyTypes = ['dependencies', 'devDependencies'];
-    dependencyTypes.forEach((depType) => {
-      if (!packageContents[depType]) {
+module.exports = function npm(setLogger) {
+  logger = setLogger;
+  this.getAllDependencyUpgrades = getAllDependencyUpgrades;
+  return this;
+};
+
+function getAllDependencyUpgrades(packageContents) {
+  const allDependencyChecks = [];
+  const allDependencyUpgrades = [];
+  const dependencyTypes = ['dependencies', 'devDependencies'];
+  dependencyTypes.forEach((depType) => {
+    if (!packageContents[depType]) {
+      return;
+    }
+    Object.keys(packageContents[depType]).forEach((depName) => {
+      const currentVersion = packageContents[depType][depName];
+      if (!isValidVersion(currentVersion)) {
+        logger.verbose(`${depName}: Skipping invalid version ${currentVersion}`);
         return;
       }
-      Object.keys(packageContents[depType]).forEach((depName) => {
-        const currentVersion = packageContents[depType][depName];
-        if (!isValidVersion(currentVersion)) {
-          logger.verbose(`${depName}: Skipping invalid version ${currentVersion}`);
-          return;
-        }
-        allDependencyChecks.push(
-          getDependencyUpgrades(depName, currentVersion).then((res) => {
-            if (res.length > 0) {
-              logger.verbose(`${depName}: Upgrades = ${JSON.stringify(res)}`);
-              res.forEach((upgrade) => {
-                allDependencyUpgrades.push({
-                  depType,
-                  depName,
-                  currentVersion,
-                  upgradeType: upgrade.type,
-                  newVersion: upgrade.version,
-                });
+      allDependencyChecks.push(
+        getDependencyUpgrades(depName, currentVersion).then((res) => {
+          if (res.length > 0) {
+            logger.verbose(`${depName}: Upgrades = ${JSON.stringify(res)}`);
+            res.forEach((upgrade) => {
+              allDependencyUpgrades.push({
+                depType,
+                depName,
+                currentVersion,
+                upgradeType: upgrade.type,
+                newVersion: upgrade.version,
               });
-            } else {
-              logger.verbose(`${depName}: No upgrades required`);
-            }
-            return Promise.resolve();
-          }));
-      });
+            });
+          } else {
+            logger.verbose(`${depName}: No upgrades required`);
+          }
+          return Promise.resolve();
+        }));
     });
-    return Promise.all(allDependencyChecks).then(() => allDependencyUpgrades);
-  },
-};
+  });
+  return Promise.all(allDependencyChecks).then(() => allDependencyUpgrades);
+}
 
 function getDependency(depName) {
   // supports scoped packages, e.g. @user/package
diff --git a/src/helpers/packageJson.js b/src/helpers/packageJson.js
index 2eb3c91db7..411a756e08 100644
--- a/src/helpers/packageJson.js
+++ b/src/helpers/packageJson.js
@@ -2,8 +2,8 @@ const _ = require('lodash');
 
 let logger = null;
 
-module.exports = function packageJson(config) {
-  logger = config.logger;
+module.exports = function packageJson(setLogger) {
+  logger = setLogger;
   this.setNewValue = setNewValue;
   return this;
 };
diff --git a/src/index.js b/src/index.js
index 029e6e1a4b..c18ebde782 100644
--- a/src/index.js
+++ b/src/index.js
@@ -1,15 +1,13 @@
 const semver = require('semver');
-const configurator = require('./helpers/config');
-
-const config = configurator.init(process.argv);
-const github = require('./helpers/github');
-const npm = require('./helpers/npm');
-const packageJson = require('./helpers/packageJson')(config);
 
+// Initialize config
+const config = require('./helpers/config')();
+// Expose logger
 const logger = config.logger;
-
-// Initialize npm
-npm.init(config);
+// Initialize helpers
+const github = require('./helpers/github')(logger);
+const npm = require('./helpers/npm')(logger);
+const packageJson = require('./helpers/packageJson')(logger);
 
 // Initialize our promise chain
 let p = Promise.resolve();
@@ -20,8 +18,7 @@ config.repositories.forEach((repo) => {
     p = p.then(() => processRepoPackageFile(repo.name, packageFile));
   });
 });
-// eslint-disable-next-line promise/always-return
-p.then(() => {
+p.then(() => { // eslint-disable-line promise/always-return
   logger.info('Renovate finished');
 })
 .catch((error) => {
@@ -30,12 +27,14 @@ p.then(() => {
 
 // This function manages the queue per-package file
 function processRepoPackageFile(repoName, packageFile) {
-  return initGitHub(repoName, packageFile)
+  return initGitHubRepo(repoName)
+    .then(() => { // eslint-disable-line arrow-body-style
+      return packageFile;
+    })
     .then(getPackageFileContents)
     .then(determineUpgrades)
     .then(processUpgradesSequentially)
-    // eslint-disable-next-line promise/always-return
-    .then(() => {
+    .then(() => { // eslint-disable-line promise/always-return
       logger.info(`Repo ${repoName} ${packageFile} done`);
     })
     .catch((error) => {
@@ -43,14 +42,14 @@ function processRepoPackageFile(repoName, packageFile) {
     });
 }
 
-function initGitHub(repoName, packageFile) {
-  logger.info(`Initializing GitHub repo ${repoName}, ${packageFile}`);
-  return github.init(config, repoName, packageFile);
+function initGitHubRepo(repoName) {
+  logger.info(`Initializing GitHub repo ${repoName}`);
+  return github.initRepo(config.token, repoName);
 }
 
-function getPackageFileContents() {
-  logger.info('Getting package file contents');
-  return github.getPackageFileContents();
+function getPackageFileContents(packageFile) {
+  logger.info(`Getting ${packageFile} contents`);
+  return github.getPackageFileContents(packageFile);
 }
 
 function determineUpgrades(packageFileContents) {
-- 
GitLab