From 3c56f8aeb66134c739eb455ee0a41df209092e3a Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Sat, 3 Mar 2018 14:39:39 +0100 Subject: [PATCH] refactor: move manager-specific code under lib/manager (#1573) Refactors all non-npm code to live inside lib/manager/* --- lib/manager/bazel/index.js | 13 ++ lib/manager/docker/index.js | 13 ++ lib/manager/index.js | 173 ++++++++++-------- lib/manager/meteor/index.js | 13 ++ lib/manager/meteor/update.js | 3 +- lib/manager/node/index.js | 13 ++ lib/manager/npm/extract.js | 8 +- lib/manager/npm/index.js | 13 ++ lib/manager/npm/update.js | 9 +- lib/manager/resolve.js | 84 --------- lib/workers/dep-type/index.js | 44 +---- lib/workers/package-file/index.js | 135 +++----------- lib/workers/repository/index.js | 2 +- lib/workers/repository/updates/determine.js | 33 +--- test/manager/index.spec.js | 38 ++-- test/manager/meteor/update.spec.js | 36 ++-- test/manager/npm/extract.spec.js | 47 +++-- test/manager/npm/update.spec.js | 72 ++++---- test/manager/resolve.spec.js | 22 ++- test/workers/package-file/index.spec.js | 21 ++- test/workers/repository/index.spec.js | 2 +- .../repository/updates/determine.spec.js | 10 +- 22 files changed, 349 insertions(+), 455 deletions(-) create mode 100644 lib/manager/bazel/index.js create mode 100644 lib/manager/docker/index.js create mode 100644 lib/manager/meteor/index.js create mode 100644 lib/manager/node/index.js create mode 100644 lib/manager/npm/index.js delete mode 100644 lib/manager/resolve.js diff --git a/lib/manager/bazel/index.js b/lib/manager/bazel/index.js new file mode 100644 index 0000000000..6b0c9b22a0 --- /dev/null +++ b/lib/manager/bazel/index.js @@ -0,0 +1,13 @@ +const { detectPackageFiles } = require('./detect'); +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('./package'); +const { resolvePackageFile } = require('./resolve'); +const { setNewValue } = require('./update'); + +module.exports = { + detectPackageFiles, + extractDependencies, + getPackageUpdates, + resolvePackageFile, + setNewValue, +}; diff --git a/lib/manager/docker/index.js b/lib/manager/docker/index.js new file mode 100644 index 0000000000..6b0c9b22a0 --- /dev/null +++ b/lib/manager/docker/index.js @@ -0,0 +1,13 @@ +const { detectPackageFiles } = require('./detect'); +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('./package'); +const { resolvePackageFile } = require('./resolve'); +const { setNewValue } = require('./update'); + +module.exports = { + detectPackageFiles, + extractDependencies, + getPackageUpdates, + resolvePackageFile, + setNewValue, +}; diff --git a/lib/manager/index.js b/lib/manager/index.js index e72fa07591..89fcbfe2e2 100644 --- a/lib/manager/index.js +++ b/lib/manager/index.js @@ -1,26 +1,20 @@ const minimatch = require('minimatch'); +const { mergeChildConfig } = require('../config'); +const { checkMonorepos } = require('../manager/npm/monorepos'); -const docker = require('./docker/package'); -const npm = require('./npm/package'); -const node = require('./node/package'); -const bazel = require('./bazel/package'); - -const dockerDetect = require('./docker/detect'); -const meteorDetect = require('./meteor/detect'); -const npmDetect = require('./npm/detect'); -const nodeDetect = require('./node/detect'); -const bazelDetect = require('./bazel/detect'); - -const npmUpdater = require('./npm/update'); -const meteorUpdater = require('./meteor/update'); -const dockerfileHelper = require('./docker/update'); -const nodeHelper = require('./node/update'); -const bazelHelper = require('./bazel/update'); +const managers = {}; +const managerList = ['bazel', 'docker', 'meteor', 'node', 'npm']; +for (const manager of managerList) { + // eslint-disable-next-line global-require,import/no-dynamic-require + managers[manager] = require(`./${manager}`); +} module.exports = { detectPackageFiles, + extractDependencies, getPackageUpdates, getUpdatedPackageFiles, + resolvePackageFiles, }; async function detectPackageFiles(config) { @@ -33,52 +27,36 @@ async function detectPackageFiles(config) { ignorePath => file.includes(ignorePath) || minimatch(file, ignorePath) ) ); - const packageJsonFiles = await npmDetect.detectPackageFiles(config, fileList); - if (packageJsonFiles.length) { - logger.info({ packageJsonFiles }, 'Found package.json files'); - packageFiles = packageFiles.concat(packageJsonFiles); - } - const meteorFiles = await meteorDetect.detectPackageFiles(config, fileList); - if (meteorFiles.length) { - logger.info({ packageJsonFiles }, 'Found meteor files'); - packageFiles = packageFiles.concat(meteorFiles); - } - const dockerFiles = await dockerDetect.detectPackageFiles(config, fileList); - if (dockerFiles.length) { - logger.info({ dockerFiles }, 'Found Dockerfiles'); - packageFiles = packageFiles.concat(dockerFiles); - } - const nodeFiles = await nodeDetect.detectPackageFiles(config, fileList); - if (nodeFiles.length) { - logger.info({ nodeFiles }, 'Found node files'); - packageFiles = packageFiles.concat(nodeFiles); - } - const bazelFiles = await bazelDetect.detectPackageFiles(config, fileList); - if (bazelFiles.length) { - logger.info({ bazelFiles }, 'Found bazel files'); - packageFiles = packageFiles.concat(bazelFiles); + for (const manager of managerList) { + logger.debug(`Detecting package files (${manager})`); + const files = await managers[manager].detectPackageFiles(config, fileList); + if (files.length) { + logger.info({ manager, files }, `Detected package files`); + packageFiles = packageFiles.concat(files); + } } + logger.debug({ packageFiles }, 'All detected package files'); return packageFiles; } +function extractDependencies(packageContent, config) { + logger.debug('manager.extractDependencies()'); + return managers[config.manager].extractDependencies(packageContent, config); +} + function getPackageUpdates(config) { + logger.debug('manager.getPackageUpdates()'); + logger.trace({ config }); const { manager } = config; - if (manager === 'docker') { - return docker.getPackageUpdates(config); - } else if (manager === 'npm') { - return npm.getPackageUpdates(config); - } else if (manager === 'meteor') { - return npm.getPackageUpdates(config); - } else if (manager === 'node') { - return node.getPackageUpdates(config); - } else if (manager === 'bazel') { - return bazel.getPackageUpdates(config); + if (!managerList.includes(manager)) { + throw new Error('Unsupported package manager'); } - logger.info(`Cannot find manager for ${config.packageFile}`); - throw new Error('Unsupported package manager'); + return managers[manager].getPackageUpdates(config); } async function getUpdatedPackageFiles(config) { + logger.debug('manager.getUpdatedPackageFiles()'); + logger.trace({ config }); const updatedPackageFiles = {}; for (const upgrade of config.upgrades) { @@ -88,32 +66,10 @@ async function getUpdatedPackageFiles(config) { updatedPackageFiles[upgrade.packageFile] || (await platform.getFile(upgrade.packageFile, config.parentBranch)); let newContent = existingContent; - if (manager === 'npm') { - newContent = npmUpdater.setNewValue( - existingContent, - upgrade.depType, - upgrade.depName, - upgrade.newVersion - ); - newContent = npmUpdater.bumpPackageVersion( - newContent, - upgrade.currentPackageJsonVersion, - upgrade.bumpVersion - ); - } else if (manager === 'meteor') { - newContent = meteorUpdater.setNewValue( - existingContent, - upgrade.depName, - upgrade.currentVersion, - upgrade.newVersion - ); - } else if (manager === 'docker') { - newContent = dockerfileHelper.setNewValue(existingContent, upgrade); - } else if (manager === 'node') { - newContent = nodeHelper.setNewValue(existingContent, upgrade); - } else if (manager === 'bazel') { - newContent = await bazelHelper.setNewValue(existingContent, upgrade); - } + newContent = await managers[manager].setNewValue( + existingContent, + upgrade + ); if (!newContent) { if (config.parentBranch) { logger.info('Rebasing branch after error updating content'); @@ -146,3 +102,64 @@ async function getUpdatedPackageFiles(config) { })), }; } + +async function resolvePackageFiles(config) { + logger.debug('manager.resolvePackageFile()'); + logger.trace({ config }); + const allPackageFiles = + config.packageFiles && config.packageFiles.length + ? config.packageFiles + : await detectPackageFiles(config); + logger.debug({ allPackageFiles }, 'allPackageFiles'); + const managerFileMappings = { + '.travis.yml': 'node', + Dockerfile: 'docker', + WORKSPACE: 'bazel', + 'package.js': 'meteor', + 'package.json': 'npm', + }; + function resolvePackageFile(p) { + const packageFile = typeof p === 'string' ? { packageFile: p } : p; + const fileName = packageFile.packageFile.split('/').pop(); + packageFile.manager = packageFile.manager || managerFileMappings[fileName]; + if (!packageFile.manager) { + // Config error + const error = new Error('config-validation'); + error.configFile = packageFile.packageFile; + error.validationError = 'Unknown file type'; + error.validationMessage = + 'Please correct the file name in your packageFiles array'; + throw error; + } + return managers[packageFile.manager].resolvePackageFile( + config, + packageFile + ); + } + // TODO: throttle how many we resolve in parallel + const queue = allPackageFiles.map(p => resolvePackageFile(p)); + let packageFiles = (await Promise.all(queue)).filter(p => p !== null); + logger.debug('Checking against path rules'); + packageFiles = packageFiles.map(pf => { + let packageFile = { ...pf }; + for (const pathRule of config.pathRules) { + /* eslint-disable no-loop-func */ + if ( + pathRule.paths.some( + rulePath => + packageFile.packageFile.includes(rulePath) || + minimatch(packageFile.packageFile, rulePath) + ) + ) { + logger.debug({ pathRule, packageFile }, 'Matched pathRule'); + packageFile = mergeChildConfig(packageFile, pathRule); + delete packageFile.paths; + } + /* eslint-enable */ + } + return packageFile; + }); + + platform.ensureIssueClosing('Action Required: Fix Renovate Configuration'); + return checkMonorepos({ ...config, packageFiles }); +} diff --git a/lib/manager/meteor/index.js b/lib/manager/meteor/index.js new file mode 100644 index 0000000000..bca51e83c5 --- /dev/null +++ b/lib/manager/meteor/index.js @@ -0,0 +1,13 @@ +const { detectPackageFiles } = require('./detect'); +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('../npm/package'); +const { resolvePackageFile } = require('./resolve'); +const { setNewValue } = require('./update'); + +module.exports = { + detectPackageFiles, + extractDependencies, + getPackageUpdates, + resolvePackageFile, + setNewValue, +}; diff --git a/lib/manager/meteor/update.js b/lib/manager/meteor/update.js index 6ebd13c616..f77dd9f03e 100644 --- a/lib/manager/meteor/update.js +++ b/lib/manager/meteor/update.js @@ -2,7 +2,8 @@ module.exports = { setNewValue, }; -function setNewValue(currentFileContent, depName, currentVersion, newVersion) { +function setNewValue(currentFileContent, upgrade) { + const { depName, currentVersion, newVersion } = upgrade; logger.debug(`setNewValue: ${depName} = ${newVersion}`); const regexReplace = new RegExp( `('|")(${depName})('|"):(\\s+)('|")${currentVersion}('|")` diff --git a/lib/manager/node/index.js b/lib/manager/node/index.js new file mode 100644 index 0000000000..6b0c9b22a0 --- /dev/null +++ b/lib/manager/node/index.js @@ -0,0 +1,13 @@ +const { detectPackageFiles } = require('./detect'); +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('./package'); +const { resolvePackageFile } = require('./resolve'); +const { setNewValue } = require('./update'); + +module.exports = { + detectPackageFiles, + extractDependencies, + getPackageUpdates, + resolvePackageFile, + setNewValue, +}; diff --git a/lib/manager/npm/extract.js b/lib/manager/npm/extract.js index 0e9f41811e..9ee4907893 100644 --- a/lib/manager/npm/extract.js +++ b/lib/manager/npm/extract.js @@ -2,12 +2,8 @@ module.exports = { extractDependencies, }; -function extractDependencies( - packageJson, - depType, - packageLockParsed, - yarnLockParsed -) { +function extractDependencies(packageJson, config) { + const { depType, packageLockParsed, yarnLockParsed } = config; const depNames = packageJson[depType] ? Object.keys(packageJson[depType]) : []; diff --git a/lib/manager/npm/index.js b/lib/manager/npm/index.js new file mode 100644 index 0000000000..6b0c9b22a0 --- /dev/null +++ b/lib/manager/npm/index.js @@ -0,0 +1,13 @@ +const { detectPackageFiles } = require('./detect'); +const { extractDependencies } = require('./extract'); +const { getPackageUpdates } = require('./package'); +const { resolvePackageFile } = require('./resolve'); +const { setNewValue } = require('./update'); + +module.exports = { + detectPackageFiles, + extractDependencies, + getPackageUpdates, + resolvePackageFile, + setNewValue, +}; diff --git a/lib/manager/npm/update.js b/lib/manager/npm/update.js index 1c2c3a3f7c..9861520328 100644 --- a/lib/manager/npm/update.js +++ b/lib/manager/npm/update.js @@ -6,7 +6,8 @@ module.exports = { bumpPackageVersion, }; -function setNewValue(currentFileContent, depType, depName, newVersion) { +function setNewValue(currentFileContent, upgrade) { + const { depType, depName, newVersion } = upgrade; logger.debug(`setNewValue: ${depType}.${depName} = ${newVersion}`); try { const parsedContents = JSON.parse(currentFileContent); @@ -94,7 +95,11 @@ function setNewValue(currentFileContent, depType, depName, newVersion) { ); } } - return newFileContent; + return bumpPackageVersion( + newFileContent, + upgrade.currentPackageJsonVersion, + upgrade.bumpVersion + ); } catch (err) { logger.info({ err }, 'setNewValue error'); return null; diff --git a/lib/manager/resolve.js b/lib/manager/resolve.js deleted file mode 100644 index b4841ad820..0000000000 --- a/lib/manager/resolve.js +++ /dev/null @@ -1,84 +0,0 @@ -const minimatch = require('minimatch'); - -const manager = require('./index'); -const dockerResolve = require('../manager/docker/resolve'); -const meteorResolve = require('../manager/meteor/resolve'); -const nodeResolve = require('../manager/node/resolve'); -const bazelResolve = require('../manager/bazel/resolve'); -const npmResolve = require('../manager/npm/resolve'); -const { mergeChildConfig } = require('../config'); -const { checkMonorepos } = require('../manager/npm/monorepos'); - -module.exports = { - resolvePackageFiles, -}; - -async function resolvePackageFiles(config) { - logger.debug('manager.resolvePackageFiles()'); - logger.trace({ config }); - const allPackageFiles = - config.packageFiles && config.packageFiles.length - ? config.packageFiles - : await manager.detectPackageFiles(config); - logger.debug({ allPackageFiles }, 'allPackageFiles'); - const managerFileMappings = { - '.travis.yml': 'node', - Dockerfile: 'docker', - WORKSPACE: 'bazel', - 'package.js': 'meteor', - 'package.json': 'npm', - }; - function resolvePackageFile(p) { - const packageFile = typeof p === 'string' ? { packageFile: p } : p; - const fileName = packageFile.packageFile.split('/').pop(); - packageFile.manager = packageFile.manager || managerFileMappings[fileName]; - if (!packageFile.manager) { - // Config error - const error = new Error('config-validation'); - error.configFile = packageFile.packageFile; - error.validationError = 'Unknown file type'; - error.validationMessage = - 'Please correct the file name in your packageFiles array'; - throw error; - } - if (packageFile.manager === 'npm') { - return npmResolve.resolvePackageFile(config, packageFile); - } else if (packageFile.manager === 'meteor') { - return meteorResolve.resolvePackageFile(config, packageFile); - } else if (packageFile.manager === 'docker') { - return dockerResolve.resolvePackageFile(config, packageFile); - } else if (packageFile.manager === 'node') { - return nodeResolve.resolvePackageFile(config, packageFile); - } else if (packageFile.manager === 'bazel') { - return bazelResolve.resolvePackageFile(config, packageFile); - } - // istanbul ignore next - throw new Error('unknown manager'); - } - // TODO: throttle how many we resolve in parallel - const queue = allPackageFiles.map(p => resolvePackageFile(p)); - let packageFiles = (await Promise.all(queue)).filter(p => p !== null); - logger.debug('Checking against path rules'); - packageFiles = packageFiles.map(pf => { - let packageFile = { ...pf }; - for (const pathRule of config.pathRules) { - /* eslint-disable no-loop-func */ - if ( - pathRule.paths.some( - rulePath => - packageFile.packageFile.includes(rulePath) || - minimatch(packageFile.packageFile, rulePath) - ) - ) { - logger.debug({ pathRule, packageFile }, 'Matched pathRule'); - packageFile = mergeChildConfig(packageFile, pathRule); - delete packageFile.paths; - } - /* eslint-enable */ - } - return packageFile; - }); - - platform.ensureIssueClosing('Action Required: Fix Renovate Configuration'); - return checkMonorepos({ ...config, packageFiles }); -} diff --git a/lib/workers/dep-type/index.js b/lib/workers/dep-type/index.js index 511b50c4c1..a31e279d13 100644 --- a/lib/workers/dep-type/index.js +++ b/lib/workers/dep-type/index.js @@ -1,57 +1,29 @@ const configParser = require('../../config'); const pkgWorker = require('../package'); -const npmExtract = require('../../manager/npm/extract'); -const dockerExtract = require('../../manager/docker/extract'); -const meteorExtract = require('../../manager/meteor/extract'); -const nodeExtract = require('../../manager/node/extract'); -const bazelExtract = require('../../manager/bazel/extract'); +const { extractDependencies } = require('../../manager'); module.exports = { renovateDepType, getDepConfig, }; -async function renovateDepType( - packageContent, - config, - packageLockParsed, - yarnLockParsed -) { +async function renovateDepType(packageContent, config) { logger.setMeta({ repository: config.repository, packageFile: config.packageFile, depType: config.depType, }); - logger.trace({ config }, `renovateDepType(packageContent, config)`); + logger.debug('renovateDepType()'); + logger.trace({ config }); if (config.enabled === false) { logger.debug('depType is disabled'); return []; } - let deps = []; - const { manager } = config; - if (manager === 'npm') { - // Extract all dependencies from the package.json - deps = await npmExtract.extractDependencies( - packageContent, - config.depType, - packageLockParsed, - yarnLockParsed + let deps = await extractDependencies(packageContent, config); + if (config.lerna || config.workspaces || config.workspaceDir) { + deps = deps.filter( + dependency => config.monorepoPackages.indexOf(dependency.depName) === -1 ); - if (config.lerna || config.workspaces || config.workspaceDir) { - deps = deps.filter( - dependency => config.monorepoPackages.indexOf(dependency.depName) === -1 - ); - } - logger.debug(`deps length is ${deps.length}`); - logger.debug({ deps }, `deps`); - } else if (manager === 'meteor') { - deps = meteorExtract.extractDependencies(packageContent); - } else if (manager === 'docker') { - deps = dockerExtract.extractDependencies(packageContent); - } else if (manager === 'node') { - deps = nodeExtract.extractDependencies(packageContent); - } else if (manager === 'bazel') { - deps = bazelExtract.extractDependencies(packageContent); } deps = deps.filter( dependency => config.ignoreDeps.indexOf(dependency.depName) === -1 diff --git a/lib/workers/package-file/index.js b/lib/workers/package-file/index.js index 48fa045be5..c4da377906 100644 --- a/lib/workers/package-file/index.js +++ b/lib/workers/package-file/index.js @@ -7,10 +7,7 @@ const upath = require('upath'); module.exports = { mightBeABrowserLibrary, renovatePackageFile, - renovateMeteorPackageFile, - renovateDockerfile, - renovateNodeFile, - renovateBazelFile, + renovatePackageJson, }; function mightBeABrowserLibrary(packageJson) { @@ -28,13 +25,26 @@ function mightBeABrowserLibrary(packageJson) { return true; } -async function renovatePackageFile(packageFileConfig) { - const config = { ...packageFileConfig }; +async function renovatePackageFile(config) { logger.setMeta({ repository: config.repository, packageFile: config.packageFile, }); - logger.debug('renovatePakageFile()'); + logger.debug('renovatePackageFile()'); + const { manager } = config; + if (config.enabled === false) { + logger.info('packageFile is disabled'); + return []; + } + if (manager === 'npm') { + return renovatePackageJson(config); + } + const content = await platform.getFile(config.packageFile); + return depTypeWorker.renovateDepType(content, config); +} + +async function renovatePackageJson(input) { + const config = { ...input }; if (config.npmrc) { logger.debug('Setting .npmrc'); npmApi.setNpmrc( @@ -45,14 +55,6 @@ async function renovatePackageFile(packageFileConfig) { let upgrades = []; logger.info(`Processing package file`); - // Check if config is disabled - if (config.enabled === false) { - logger.info('packageFile is disabled'); - return upgrades; - } - - let yarnLockParsed; - let packageLockParsed; let { yarnLock } = config; if (!yarnLock && config.workspaceDir) { yarnLock = upath.join(config.workspaceDir, 'yarn.lock'); @@ -65,24 +67,26 @@ async function renovatePackageFile(packageFileConfig) { } if (yarnLock) { try { - yarnLockParsed = yarnLockParser.parse(await platform.getFile(yarnLock)); - if (yarnLockParsed.type !== 'success') { + config.yarnLockParsed = yarnLockParser.parse( + await platform.getFile(yarnLock) + ); + if (config.yarnLockParsed.type !== 'success') { logger.info( - { type: yarnLockParsed.type }, + { type: config.yarnLockParsed.type }, 'Error parsing yarn.lock - not success' ); - yarnLockParsed = undefined; + delete config.yarnLockParsed; } - logger.trace({ yarnLockParsed }); + logger.trace({ yarnLockParsed: config.yarnLockParsed }); } catch (err) { logger.info({ yarnLock }, 'Warning: Exception parsing yarn.lock'); } } else if (config.packageLock) { try { - packageLockParsed = JSON.parse( + config.packageLockParsed = JSON.parse( await platform.getFile(config.packageLock) ); - logger.trace({ packageLockParsed }); + logger.trace({ packageLockParsed: config.packageLockParsed }); } catch (err) { logger.warn( { packageLock: config.packageLock }, @@ -119,19 +123,9 @@ async function renovatePackageFile(packageFileConfig) { logger.trace({ config: depTypeConfigs }, `depTypeConfigs`); for (const depTypeConfig of depTypeConfigs) { upgrades = upgrades.concat( - await depTypeWorker.renovateDepType( - config.content, - depTypeConfig, - packageLockParsed, - yarnLockParsed - ) + await depTypeWorker.renovateDepType(config.content, depTypeConfig) ); } - // Reset logger again - logger.setMeta({ - repository: config.repository, - packageFile: config.packageFile, - }); if ( config.lockFileMaintenance.enabled && (config.yarnLock || config.packageLock) @@ -153,78 +147,3 @@ async function renovatePackageFile(packageFileConfig) { logger.info('Finished processing package file'); return upgrades; } - -async function renovateMeteorPackageFile(packageFileConfig) { - const config = { ...packageFileConfig }; - let upgrades = []; - logger.info(`Processing meteor package file`); - - // Check if config is disabled - if (config.enabled === false) { - logger.info('packageFile is disabled'); - return upgrades; - } - const content = await platform.getFile(packageFileConfig.packageFile); - upgrades = upgrades.concat( - await depTypeWorker.renovateDepType(content, packageFileConfig) - ); - logger.info('Finished processing package file'); - return upgrades; -} - -async function renovateDockerfile(packageFileConfig) { - let upgrades = []; - logger.info(`Processing Dockerfile`); - - // Check if config is disabled - if (packageFileConfig.enabled === false) { - logger.info('Dockerfile is disabled'); - return upgrades; - } - upgrades = upgrades.concat( - await depTypeWorker.renovateDepType( - packageFileConfig.content, - packageFileConfig - ) - ); - logger.info('Finished processing Dockerfile'); - return upgrades; -} - -async function renovateNodeFile(packageFileConfig) { - let upgrades = []; - logger.info(`Processing node file`); - - // Check if config is disabled - if (packageFileConfig.enabled === false) { - logger.info('node is disabled'); - return upgrades; - } - upgrades = upgrades.concat( - await depTypeWorker.renovateDepType( - packageFileConfig.content, - packageFileConfig - ) - ); - logger.info('Finished processing node file'); - return upgrades; -} - -async function renovateBazelFile(packageFileConfig) { - let upgrades = []; - logger.info(`Processing bazel WORKSPACE file`); - - // Check if config is disabled - if (packageFileConfig.enabled === false) { - logger.info('bazel is disabled'); - return upgrades; - } - upgrades = upgrades.concat( - await depTypeWorker.renovateDepType( - packageFileConfig.content, - packageFileConfig - ) - ); - logger.info('Finished processing bazel file'); - return upgrades; -} diff --git a/lib/workers/repository/index.js b/lib/workers/repository/index.js index bc511240fe..a0cba552b6 100644 --- a/lib/workers/repository/index.js +++ b/lib/workers/repository/index.js @@ -6,7 +6,7 @@ const { writeUpdates } = require('./write'); const { handleError } = require('./error'); const { pruneStaleBranches } = require('./cleanup'); -const { resolvePackageFiles } = require('../../manager/resolve'); +const { resolvePackageFiles } = require('../../manager'); module.exports = { renovateRepository, diff --git a/lib/workers/repository/updates/determine.js b/lib/workers/repository/updates/determine.js index 5c23fd0e54..058864e760 100644 --- a/lib/workers/repository/updates/determine.js +++ b/lib/workers/repository/updates/determine.js @@ -17,36 +17,9 @@ async function determineRepoUpgrades(config) { logger.trace({ fullPackageFile: packageFile }); let packageFileConfig = mergeChildConfig(config, packageFile); packageFileConfig = filterConfig(packageFileConfig, 'packageFile'); - const { manager } = packageFileConfig; - if (manager === 'npm') { - logger.info( - { packageFile: packageFileConfig.packageFile }, - 'Renovating package.json dependencies' - ); - upgrades = upgrades.concat( - await packageFileWorker.renovatePackageFile(packageFileConfig) - ); - } else if (manager === 'meteor') { - logger.info('Renovating package.js (meteor) dependencies'); - upgrades = upgrades.concat( - await packageFileWorker.renovateMeteorPackageFile(packageFileConfig) - ); - } else if (manager === 'docker') { - logger.info('Renovating Dockerfile FROM'); - upgrades = upgrades.concat( - await packageFileWorker.renovateDockerfile(packageFileConfig) - ); - } else if (manager === 'node') { - logger.info('Renovating .travis.yml node_js versions'); - upgrades = upgrades.concat( - await packageFileWorker.renovateNodeFile(packageFileConfig) - ); - } else if (manager === 'bazel') { - logger.info('Renovating bazel WORKSPACE dependencies'); - upgrades = upgrades.concat( - await packageFileWorker.renovateBazelFile(packageFileConfig) - ); - } + upgrades = upgrades.concat( + await packageFileWorker.renovatePackageFile(packageFileConfig) + ); } let semanticCommits; if (upgrades.length) { diff --git a/test/manager/index.spec.js b/test/manager/index.spec.js index 0e40534f50..816de7d641 100644 --- a/test/manager/index.spec.js +++ b/test/manager/index.spec.js @@ -1,10 +1,10 @@ const defaultConfig = require('../../lib/config/defaults').getConfig(); const manager = require('../../lib/manager'); -const npmUpdater = require('../../lib/manager/npm/update'); -const meteorUpdater = require('../../lib/manager/meteor/update'); -const dockerUpdater = require('../../lib/manager/docker/update'); -const nodeUpdater = require('../../lib/manager/node/update'); -const bazelUpdater = require('../../lib/manager/bazel/update'); +const npm = require('../../lib/manager/npm'); +const meteor = require('../../lib/manager/meteor'); +const docker = require('../../lib/manager/docker'); +const node = require('../../lib/manager/node'); +const bazel = require('../../lib/manager/bazel'); const path = require('path'); const fs = require('fs-extra'); @@ -120,11 +120,11 @@ describe('manager', () => { ...defaultConfig, parentBranch: 'some-branch', }; - npmUpdater.setNewValue = jest.fn(); - dockerUpdater.setNewValue = jest.fn(); - meteorUpdater.setNewValue = jest.fn(); - nodeUpdater.setNewValue = jest.fn(); - bazelUpdater.setNewValue = jest.fn(); + npm.setNewValue = jest.fn(); + docker.setNewValue = jest.fn(); + meteor.setNewValue = jest.fn(); + node.setNewValue = jest.fn(); + bazel.setNewValue = jest.fn(); }); it('returns empty if lock file maintenance', async () => { config.upgrades = [{ type: 'lockFileMaintenance' }]; @@ -135,13 +135,13 @@ describe('manager', () => { config.parentBranch = 'some-branch'; config.canRebase = true; config.upgrades = [{ packageFile: 'package.json', manager: 'npm' }]; - npmUpdater.setNewValue.mockReturnValueOnce(null); - npmUpdater.setNewValue.mockReturnValueOnce('some content'); + npm.setNewValue.mockReturnValueOnce(null); + npm.setNewValue.mockReturnValueOnce('some content'); const res = await getUpdatedPackageFiles(config); expect(res.updatedPackageFiles).toHaveLength(1); }); it('errors if cannot rebase', async () => { - config.upgrades = [{ packageFile: 'package.json' }]; + config.upgrades = [{ packageFile: 'package.json', manager: 'npm' }]; let e; try { await getUpdatedPackageFiles(config); @@ -166,12 +166,12 @@ describe('manager', () => { platform.getFile.mockReturnValueOnce('old content 3'); platform.getFile.mockReturnValueOnce('old travis'); platform.getFile.mockReturnValueOnce('old WORKSPACE'); - npmUpdater.setNewValue.mockReturnValueOnce('new content 1'); - npmUpdater.setNewValue.mockReturnValueOnce('new content 1+'); - dockerUpdater.setNewValue.mockReturnValueOnce('new content 2'); - meteorUpdater.setNewValue.mockReturnValueOnce('old content 3'); - nodeUpdater.setNewValue.mockReturnValueOnce('old travis'); - bazelUpdater.setNewValue.mockReturnValueOnce('old WORKSPACE'); + npm.setNewValue.mockReturnValueOnce('new content 1'); + npm.setNewValue.mockReturnValueOnce('new content 1+'); + docker.setNewValue.mockReturnValueOnce('new content 2'); + meteor.setNewValue.mockReturnValueOnce('old content 3'); + node.setNewValue.mockReturnValueOnce('old travis'); + bazel.setNewValue.mockReturnValueOnce('old WORKSPACE'); const res = await getUpdatedPackageFiles(config); expect(res.updatedPackageFiles).toHaveLength(2); }); diff --git a/test/manager/meteor/update.spec.js b/test/manager/meteor/update.spec.js index 8d7c16567b..3eceb24399 100644 --- a/test/manager/meteor/update.spec.js +++ b/test/manager/meteor/update.spec.js @@ -15,30 +15,30 @@ const input02Content = readFixture('package-2.js'); describe('workers/branch/package-js', () => { describe('.setNewValue(currentFileContent, depName, currentVersion, newVersion)', () => { it('replaces a dependency value', () => { - const testContent = meteorUpdater.setNewValue( - input01Content, - 'xmldom', - '0.1.19', - '0.22.1' - ); + const upgrade = { + depName: 'xmldom', + currentVersion: '0.1.19', + newVersion: '0.22.1', + }; + const testContent = meteorUpdater.setNewValue(input01Content, upgrade); expect(testContent).toMatchSnapshot(); }); it('handles alternative quotes and white space', () => { - const testContent = meteorUpdater.setNewValue( - input02Content, - 'xmldom', - '0.1.19', - '0.22.1' - ); + const upgrade = { + depName: 'xmldom', + currentVersion: '0.1.19', + newVersion: '0.22.1', + }; + const testContent = meteorUpdater.setNewValue(input02Content, upgrade); expect(testContent).toMatchSnapshot(); }); it('handles the case where the desired version is already supported', () => { - const testContent = meteorUpdater.setNewValue( - input01Content, - 'query-string', - '0.2.0', - '0.2.0' - ); + const upgrade = { + depName: 'query-string', + currentVersion: '0.2.0', + newVersion: '0.2.0', + }; + const testContent = meteorUpdater.setNewValue(input01Content, upgrade); testContent.should.equal(input01Content); }); }); diff --git a/test/manager/npm/extract.spec.js b/test/manager/npm/extract.spec.js index 29a62c8e10..42a0e9619d 100644 --- a/test/manager/npm/extract.spec.js +++ b/test/manager/npm/extract.spec.js @@ -15,25 +15,34 @@ const input02Content = readFixture('inputs/02.json'); describe('workers/dep-type/package-json', () => { describe('.extractDependencies(npmExtract, depType)', () => { it('returns an array of correct length (dependencies)', () => { + const config = { + depType: 'dependencies', + }; const extractedDependencies = npmExtract.extractDependencies( JSON.parse(input01Content), - 'dependencies' + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(6); }); it('returns an array of correct length (devDependencies)', () => { + const config = { + depType: 'devDependencies', + }; const extractedDependencies = npmExtract.extractDependencies( JSON.parse(input01Content), - 'devDependencies' + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(4); }); it('each element contains non-null depType, depName, currentVersion', () => { + const config = { + depType: 'dependencies', + }; const extractedDependencies = npmExtract.extractDependencies( JSON.parse(input01Content), - 'dependencies' + config ); expect(extractedDependencies).toMatchSnapshot(); extractedDependencies @@ -41,17 +50,23 @@ describe('workers/dep-type/package-json', () => { .should.eql(true); }); it('supports null devDependencies indirect', () => { + const config = { + depType: 'dependencies', + }; const extractedDependencies = npmExtract.extractDependencies( JSON.parse(input02Content), - 'dependencies' + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(6); }); it('supports null', () => { + const config = { + depType: 'fooDpendencies', + }; const extractedDependencies = npmExtract.extractDependencies( JSON.parse(input02Content), - 'fooDependencies' + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(0); @@ -60,10 +75,13 @@ describe('workers/dep-type/package-json', () => { const packageLockParsed = { dependencies: { chalk: { version: '2.0.1' } }, }; + const config = { + depType: 'dependencies', + packageLockParsed, + }; const extractedDependencies = npmExtract.extractDependencies( { dependencies: { chalk: '^2.0.0', foo: '^1.0.0' } }, - 'dependencies', - packageLockParsed + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(2); @@ -74,11 +92,13 @@ describe('workers/dep-type/package-json', () => { const yarnLockParsed = { object: { 'chalk@^2.0.0': { version: '2.0.1' } }, }; + const config = { + depType: 'dependencies', + yarnLockParsed, + }; const extractedDependencies = npmExtract.extractDependencies( { dependencies: { chalk: '^2.0.0', foo: '^1.0.0' } }, - 'dependencies', - undefined, - yarnLockParsed + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(2); @@ -86,10 +106,13 @@ describe('workers/dep-type/package-json', () => { expect(extractedDependencies[1].lockedVersion).toBeUndefined(); }); it('handles lock error', () => { + const config = { + depType: 'dependencies', + packageLockParsed: true, + }; const extractedDependencies = npmExtract.extractDependencies( { dependencies: { chalk: '^2.0.0', foo: '^1.0.0' } }, - 'dependencies', - true + config ); extractedDependencies.should.be.instanceof(Array); extractedDependencies.should.have.length(2); diff --git a/test/manager/npm/update.spec.js b/test/manager/npm/update.spec.js index 46d6516c9e..885ffd61b0 100644 --- a/test/manager/npm/update.spec.js +++ b/test/manager/npm/update.spec.js @@ -15,61 +15,61 @@ const input01Content = readFixture('inputs/01.json'); describe('workers/branch/package-json', () => { describe('.setNewValue(currentFileContent, depType, depName, newVersion)', () => { it('replaces a dependency value', () => { + const upgrade = { + depType: 'dependencies', + depName: 'cheerio', + newVersion: '0.22.1', + }; const outputContent = readFixture('outputs/011.json'); - const testContent = npmUpdater.setNewValue( - input01Content, - 'dependencies', - 'cheerio', - '0.22.1' - ); + const testContent = npmUpdater.setNewValue(input01Content, upgrade); testContent.should.equal(outputContent); }); it('updates resolutions too', () => { - const testContent = npmUpdater.setNewValue( - input01Content, - 'dependencies', - 'config', - '1.22.0' - ); + const upgrade = { + depType: 'dependencies', + depName: 'config', + newVersion: '1.22.0', + }; + const testContent = npmUpdater.setNewValue(input01Content, upgrade); expect(JSON.parse(testContent).dependencies.config).toEqual('1.22.0'); expect(JSON.parse(testContent).resolutions.config).toEqual('1.22.0'); }); it('replaces only the first instance of a value', () => { + const upgrade = { + depType: 'devDependencies', + depName: 'angular-touch', + newVersion: '1.6.1', + }; const outputContent = readFixture('outputs/012.json'); - const testContent = npmUpdater.setNewValue( - input01Content, - 'devDependencies', - 'angular-touch', - '1.6.1' - ); + const testContent = npmUpdater.setNewValue(input01Content, upgrade); testContent.should.equal(outputContent); }); it('replaces only the second instance of a value', () => { + const upgrade = { + depType: 'devDependencies', + depName: 'angular-sanitize', + newVersion: '1.6.1', + }; const outputContent = readFixture('outputs/013.json'); - const testContent = npmUpdater.setNewValue( - input01Content, - 'devDependencies', - 'angular-sanitize', - '1.6.1' - ); + const testContent = npmUpdater.setNewValue(input01Content, upgrade); testContent.should.equal(outputContent); }); it('handles the case where the desired version is already supported', () => { - const testContent = npmUpdater.setNewValue( - input01Content, - 'devDependencies', - 'angular-touch', - '1.5.8' - ); + const upgrade = { + depType: 'devDependencies', + depName: 'angular-touch', + newVersion: '1.5.8', + }; + const testContent = npmUpdater.setNewValue(input01Content, upgrade); testContent.should.equal(input01Content); }); it('returns null if throws error', () => { - const testContent = npmUpdater.setNewValue( - input01Content, - 'blah', - 'angular-touch-not', - '1.5.8' - ); + const upgrade = { + depType: 'blah', + depName: 'angular-touch-not', + newVersion: '1.5.8', + }; + const testContent = npmUpdater.setNewValue(input01Content, upgrade); expect(testContent).toBe(null); }); }); diff --git a/test/manager/resolve.spec.js b/test/manager/resolve.spec.js index 32d1f8b85b..c30ff35c6d 100644 --- a/test/manager/resolve.spec.js +++ b/test/manager/resolve.spec.js @@ -1,6 +1,7 @@ -const { resolvePackageFiles } = require('../../lib/manager/resolve'); const manager = require('../../lib/manager'); +const { resolvePackageFiles } = manager; + let config; beforeEach(() => { jest.resetAllMocks(); @@ -33,8 +34,9 @@ describe('manager/resolve', () => { }); it('detect package.json and adds error if cannot parse (onboarding)', async () => { manager.detectPackageFiles = jest.fn(() => [ - { packageFile: 'package.json' }, + { packageFile: 'package.json', manager: 'npm' }, ]); + platform.getFileList.mockReturnValue(['package.json']); platform.getFile.mockReturnValueOnce('not json'); const res = await resolvePackageFiles(config); expect(res.packageFiles).toMatchSnapshot(); @@ -42,8 +44,9 @@ describe('manager/resolve', () => { }); it('detect package.json and throws error if cannot parse (onboarded)', async () => { manager.detectPackageFiles = jest.fn(() => [ - { packageFile: 'package.json' }, + { packageFile: 'package.json', manager: 'npm' }, ]); + platform.getFileList.mockReturnValue(['package.json']); platform.getFile.mockReturnValueOnce('not json'); config.repoIsOnboarded = true; let e; @@ -57,7 +60,7 @@ describe('manager/resolve', () => { }); it('clears npmrc and yarnrc fields', async () => { manager.detectPackageFiles = jest.fn(() => [ - { packageFile: 'package.json' }, + { packageFile: 'package.json', manager: 'npm' }, ]); const pJson = { name: 'something', @@ -67,16 +70,17 @@ describe('manager/resolve', () => { }, }; platform.getFile.mockReturnValueOnce(JSON.stringify(pJson)); - platform.getFileList.mockReturnValueOnce([]); + platform.getFileList.mockReturnValue(['package.json']); const res = await resolvePackageFiles(config); expect(res.packageFiles).toMatchSnapshot(); expect(res.warnings).toHaveLength(0); }); it('detects accompanying files', async () => { manager.detectPackageFiles = jest.fn(() => [ - { packageFile: 'package.json' }, + { packageFile: 'package.json', manager: 'npm' }, ]); - platform.getFileList.mockReturnValueOnce([ + platform.getFileList.mockReturnValue([ + 'package.json', 'yarn.lock', 'package-lock.json', 'shrinkwrap.yaml', @@ -143,9 +147,9 @@ describe('manager/resolve', () => { }); it('strips npmrc with NPM_TOKEN', async () => { manager.detectPackageFiles = jest.fn(() => [ - { packageFile: 'package.json' }, + { packageFile: 'package.json', manager: 'npm' }, ]); - platform.getFileList.mockReturnValueOnce(['package.json', '.npmrc']); + platform.getFileList.mockReturnValue(['package.json', '.npmrc']); platform.getFile.mockReturnValueOnce( '{"name": "package.json", "version": "0.0.1"}' ); diff --git a/test/workers/package-file/index.spec.js b/test/workers/package-file/index.spec.js index 35a6ee5cf8..e37db5f1e8 100644 --- a/test/workers/package-file/index.spec.js +++ b/test/workers/package-file/index.spec.js @@ -15,6 +15,7 @@ describe('packageFileWorker', () => { config = { ...defaultConfig, packageFile: 'package.json', + manager: 'npm', content: {}, repoIsOnboarded: true, npmrc: '# nothing', @@ -92,18 +93,19 @@ describe('packageFileWorker', () => { config = { ...defaultConfig, packageFile: 'package.js', + manager: 'meteor', repoIsOnboarded: true, }; depTypeWorker.renovateDepType.mockReturnValue([]); }); it('returns empty if disabled', async () => { config.enabled = false; - const res = await packageFileWorker.renovateMeteorPackageFile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toEqual([]); }); it('returns upgrades', async () => { depTypeWorker.renovateDepType.mockReturnValueOnce([{}, {}]); - const res = await packageFileWorker.renovateMeteorPackageFile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toHaveLength(2); }); }); @@ -113,18 +115,19 @@ describe('packageFileWorker', () => { config = { ...defaultConfig, packageFile: 'WORKSPACE', + manager: 'bazel', repoIsOnboarded: true, }; depTypeWorker.renovateDepType.mockReturnValue([]); }); it('returns empty if disabled', async () => { config.enabled = false; - const res = await packageFileWorker.renovateBazelFile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toEqual([]); }); it('returns upgrades', async () => { depTypeWorker.renovateDepType.mockReturnValueOnce([{}, {}]); - const res = await packageFileWorker.renovateBazelFile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toHaveLength(2); }); }); @@ -134,18 +137,19 @@ describe('packageFileWorker', () => { config = { ...defaultConfig, packageFile: '.travis.yml', + manager: 'node', repoIsOnboarded: true, }; depTypeWorker.renovateDepType.mockReturnValue([]); }); it('returns empty if disabled', async () => { config.enabled = false; - const res = await packageFileWorker.renovateNodeFile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toEqual([]); }); it('returns upgrades', async () => { depTypeWorker.renovateDepType.mockReturnValueOnce([{}]); - const res = await packageFileWorker.renovateNodeFile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toHaveLength(1); }); }); @@ -155,18 +159,19 @@ describe('packageFileWorker', () => { config = { ...defaultConfig, packageFile: 'Dockerfile', + manager: 'docker', repoIsOnboarded: true, }; depTypeWorker.renovateDepType.mockReturnValue([]); }); it('returns empty if disabled', async () => { config.enabled = false; - const res = await packageFileWorker.renovateDockerfile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toEqual([]); }); it('returns upgrades', async () => { depTypeWorker.renovateDepType.mockReturnValueOnce([{}, {}]); - const res = await packageFileWorker.renovateDockerfile(config); + const res = await packageFileWorker.renovatePackageFile(config); expect(res).toHaveLength(2); }); }); diff --git a/test/workers/repository/index.spec.js b/test/workers/repository/index.spec.js index 4a821c5b99..7083cf9fe6 100644 --- a/test/workers/repository/index.spec.js +++ b/test/workers/repository/index.spec.js @@ -12,7 +12,7 @@ jest.mock('../../../lib/workers/repository/updates'); jest.mock('../../../lib/workers/repository/onboarding/pr'); jest.mock('../../../lib/workers/repository/write'); jest.mock('../../../lib/workers/repository/cleanup'); -jest.mock('../../../lib/manager/resolve'); +jest.mock('../../../lib/manager'); let config; beforeEach(() => { diff --git a/test/workers/repository/updates/determine.spec.js b/test/workers/repository/updates/determine.spec.js index a4ab7bf396..795489be96 100644 --- a/test/workers/repository/updates/determine.spec.js +++ b/test/workers/repository/updates/determine.spec.js @@ -50,18 +50,16 @@ describe('workers/repository/updates/determine', () => { manager: 'bazel', }, ]; - packageFileWorker.renovateDockerfile.mockReturnValueOnce([ + packageFileWorker.renovatePackageFile.mockReturnValueOnce([ { depName: 'a' }, ]); packageFileWorker.renovatePackageFile.mockReturnValueOnce([ { depName: 'b' }, { depName: 'c' }, ]); - packageFileWorker.renovateMeteorPackageFile.mockReturnValueOnce([ - { foo: 'd' }, - ]); - packageFileWorker.renovateNodeFile.mockReturnValueOnce([{ foo: 'e' }]); - packageFileWorker.renovateBazelFile.mockReturnValueOnce([{ bar: 'f' }]); + packageFileWorker.renovatePackageFile.mockReturnValueOnce([{ foo: 'd' }]); + packageFileWorker.renovatePackageFile.mockReturnValueOnce([{ foo: 'e' }]); + packageFileWorker.renovatePackageFile.mockReturnValueOnce([{ bar: 'f' }]); const res = await determineRepoUpgrades(config); expect(res.upgrades).toHaveLength(6); }); -- GitLab