From dde5756488084fdd1de7bc95f9e4a7bcad0f9e15 Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@arkins.net> Date: Sun, 4 Mar 2018 15:52:06 +0100 Subject: [PATCH] feat: .nvmrc files (#1582) Adds initial support for `.nvmrc` renovation. If the existing value is a fully-specified semver version then it will be upgraded, otherwise left alone. Closes #1270 --- lib/config/definitions.js | 7 ++++++ lib/manager/index.js | 3 ++- lib/manager/nvm/detect.js | 13 +++++++++++ lib/manager/nvm/extract.js | 13 +++++++++++ lib/manager/nvm/index.js | 13 +++++++++++ lib/manager/nvm/package.js | 10 +++++++++ lib/manager/nvm/resolve.js | 19 ++++++++++++++++ lib/manager/nvm/update.js | 8 +++++++ lib/workers/pr/index.js | 6 ++++- test/manager/__snapshots__/index.spec.js.snap | 6 +++++ .../__snapshots__/resolve.spec.js.snap | 16 ++++++++++---- test/manager/index.spec.js | 7 ++++++ .../nvm/__snapshots__/extract.spec.js.snap | 11 ++++++++++ .../nvm/__snapshots__/package.spec.js.snap | 3 +++ .../nvm/__snapshots__/update.spec.js.snap | 6 +++++ test/manager/nvm/extract.spec.js | 10 +++++++++ test/manager/nvm/package.spec.js | 22 +++++++++++++++++++ test/manager/nvm/update.spec.js | 13 +++++++++++ test/manager/resolve.spec.js | 6 +++-- .../2017-10-05-configuration-options.md | 11 ++++++++++ 20 files changed, 195 insertions(+), 8 deletions(-) create mode 100644 lib/manager/nvm/detect.js create mode 100644 lib/manager/nvm/extract.js create mode 100644 lib/manager/nvm/index.js create mode 100644 lib/manager/nvm/package.js create mode 100644 lib/manager/nvm/resolve.js create mode 100644 lib/manager/nvm/update.js create mode 100644 test/manager/nvm/__snapshots__/extract.spec.js.snap create mode 100644 test/manager/nvm/__snapshots__/package.spec.js.snap create mode 100644 test/manager/nvm/__snapshots__/update.spec.js.snap create mode 100644 test/manager/nvm/extract.spec.js create mode 100644 test/manager/nvm/package.spec.js create mode 100644 test/manager/nvm/update.spec.js diff --git a/lib/config/definitions.js b/lib/config/definitions.js index 06509ca99e..02ff369a40 100644 --- a/lib/config/definitions.js +++ b/lib/config/definitions.js @@ -780,6 +780,13 @@ const options = [ default: { enabled: false }, mergeable: true, }, + { + name: 'nvm', + description: 'Configuration object for .nvmrc files', + state: 'repository', + type: 'json', + default: { enabled: true }, + }, { name: 'docker', description: 'Configuration object for Dockerfile renovation', diff --git a/lib/manager/index.js b/lib/manager/index.js index 9ec78db90b..c1c1a6ef11 100644 --- a/lib/manager/index.js +++ b/lib/manager/index.js @@ -3,7 +3,7 @@ const { mergeChildConfig } = require('../config'); const { checkMonorepos } = require('../manager/npm/monorepos'); const managers = {}; -const managerList = ['bazel', 'docker', 'meteor', 'npm', 'travis']; +const managerList = ['bazel', 'docker', 'meteor', 'npm', 'nvm', 'travis']; for (const manager of managerList) { // eslint-disable-next-line global-require,import/no-dynamic-require managers[manager] = require(`./${manager}`); @@ -112,6 +112,7 @@ async function resolvePackageFiles(config) { : await detectPackageFiles(config); logger.debug({ allPackageFiles }, 'allPackageFiles'); const managerFileMappings = { + '.nvmrc': 'nvm', '.travis.yml': 'travis', Dockerfile: 'docker', WORKSPACE: 'bazel', diff --git a/lib/manager/nvm/detect.js b/lib/manager/nvm/detect.js new file mode 100644 index 0000000000..922bc40d18 --- /dev/null +++ b/lib/manager/nvm/detect.js @@ -0,0 +1,13 @@ +module.exports = { + detectPackageFiles, +}; + +function detectPackageFiles(config, fileList) { + logger.debug('nvm.detectPackageFiles()'); + if (config.nvm.enabled) { + if (fileList.includes('.nvmrc')) { + return ['.nvmrc']; + } + } + return []; +} diff --git a/lib/manager/nvm/extract.js b/lib/manager/nvm/extract.js new file mode 100644 index 0000000000..9d21119433 --- /dev/null +++ b/lib/manager/nvm/extract.js @@ -0,0 +1,13 @@ +module.exports = { + extractDependencies, +}; + +function extractDependencies(packageContent) { + return [ + { + depName: 'node', + depType: '.nvmrc', + currentVersion: packageContent.trim(), + }, + ]; +} diff --git a/lib/manager/nvm/index.js b/lib/manager/nvm/index.js new file mode 100644 index 0000000000..6b0c9b22a0 --- /dev/null +++ b/lib/manager/nvm/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/nvm/package.js b/lib/manager/nvm/package.js new file mode 100644 index 0000000000..75a8b35efd --- /dev/null +++ b/lib/manager/nvm/package.js @@ -0,0 +1,10 @@ +const nodeManager = require('../_helpers/node/package'); + +module.exports = { + getPackageUpdates, +}; + +function getPackageUpdates(config) { + logger.debug('nvm.getPackageUpdates()'); + return nodeManager.getPackageUpdates(config); +} diff --git a/lib/manager/nvm/resolve.js b/lib/manager/nvm/resolve.js new file mode 100644 index 0000000000..f39498a03f --- /dev/null +++ b/lib/manager/nvm/resolve.js @@ -0,0 +1,19 @@ +const { mergeChildConfig } = require('../../config'); + +module.exports = { + resolvePackageFile, +}; + +async function resolvePackageFile(config, inputFile) { + const nvmConfig = mergeChildConfig(config.node, config.nvm); + const packageFile = mergeChildConfig(nvmConfig, inputFile); + logger.debug( + `Resolving packageFile ${JSON.stringify(packageFile.packageFile)}` + ); + packageFile.content = await platform.getFile(packageFile.packageFile); + if (!packageFile.content) { + logger.debug('No packageFile content'); + return null; + } + return packageFile; +} diff --git a/lib/manager/nvm/update.js b/lib/manager/nvm/update.js new file mode 100644 index 0000000000..3d371c5a8c --- /dev/null +++ b/lib/manager/nvm/update.js @@ -0,0 +1,8 @@ +module.exports = { + setNewValue, +}; + +function setNewValue(currentFileContent, upgrade) { + logger.debug(`nvm.setNewValue: ${upgrade.newVersions}`); + return `${upgrade.newVersion}\n`; +} diff --git a/lib/workers/pr/index.js b/lib/workers/pr/index.js index c5b945846a..88d8a12b47 100644 --- a/lib/workers/pr/index.js +++ b/lib/workers/pr/index.js @@ -111,7 +111,11 @@ async function ensurePr(prConfig) { processedUpgrades.push(upgradeKey); let logJSON; - if (upgrade.depType !== 'engines') { + if ( + upgrade.manager !== 'travis' && + upgrade.manager !== 'nvm' && + upgrade.depType !== 'engines' + ) { logJSON = await changelogHelper.getChangeLogJSON( upgrade.depName, upgrade.changeLogFromVersion, diff --git a/test/manager/__snapshots__/index.spec.js.snap b/test/manager/__snapshots__/index.spec.js.snap index cf561e12e6..91c455b749 100644 --- a/test/manager/__snapshots__/index.spec.js.snap +++ b/test/manager/__snapshots__/index.spec.js.snap @@ -7,6 +7,12 @@ Array [ ] `; +exports[`manager detectPackageFiles(config) finds .nvmrc files 1`] = ` +Array [ + ".nvmrc", +] +`; + exports[`manager detectPackageFiles(config) finds .travis.yml files 1`] = ` Array [ ".travis.yml", diff --git a/test/manager/__snapshots__/resolve.spec.js.snap b/test/manager/__snapshots__/resolve.spec.js.snap index 6f661ff19a..643d46f1b7 100644 --- a/test/manager/__snapshots__/resolve.spec.js.snap +++ b/test/manager/__snapshots__/resolve.spec.js.snap @@ -42,7 +42,7 @@ Array [ ] `; -exports[`manager/resolve resolvePackageFiles() detects meteor and docker and travis and bazel 1`] = ` +exports[`manager/resolve resolvePackageFiles() detects meteor and docker and travis and bazel and nvm 1`] = ` Array [ Object { "content": "{}", @@ -270,8 +270,7 @@ This PR has been generated by [Renovate Bot](https://renovateapp.com).", "prTitle": "Update {{{depName}}} Dockerfile tag to {{#if isMajor}}v{{{newVersionMajor}}}{{else}}v{{{newTag}}}{{/if}}", }, Object { - "content": "hello: world -", + "content": "# travis", "enabled": false, "groupName": "node.js", "lazyGrouping": false, @@ -279,11 +278,20 @@ This PR has been generated by [Renovate Bot](https://renovateapp.com).", "packageFile": ".travis.yml", }, Object { - "content": "# travis", + "content": "# WORKSPACE", "enabled": true, "manager": "bazel", "packageFile": "WORKSPACE", }, + Object { + "content": "8.9 +", + "enabled": true, + "groupName": "node.js", + "lazyGrouping": false, + "manager": "nvm", + "packageFile": ".nvmrc", + }, ] `; diff --git a/test/manager/index.spec.js b/test/manager/index.spec.js index e6f5687d20..cc56dc3f95 100644 --- a/test/manager/index.spec.js +++ b/test/manager/index.spec.js @@ -78,6 +78,13 @@ describe('manager', () => { expect(res).toMatchSnapshot(); expect(res).toHaveLength(1); }); + it('finds .nvmrc files', async () => { + config.travis.enabled = true; + platform.getFileList.mockReturnValueOnce(['.nvmrc', 'other/.nvmrc']); + const res = await manager.detectPackageFiles(config); + expect(res).toMatchSnapshot(); + expect(res).toHaveLength(1); + }); it('finds WORKSPACE files', async () => { config.bazel.enabled = true; platform.getFileList.mockReturnValueOnce([ diff --git a/test/manager/nvm/__snapshots__/extract.spec.js.snap b/test/manager/nvm/__snapshots__/extract.spec.js.snap new file mode 100644 index 0000000000..1b783d2a47 --- /dev/null +++ b/test/manager/nvm/__snapshots__/extract.spec.js.snap @@ -0,0 +1,11 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/manager/nvm/extract extractDependencies() returns a result 1`] = ` +Array [ + Object { + "currentVersion": "8.4.0", + "depName": "node", + "depType": ".nvmrc", + }, +] +`; diff --git a/test/manager/nvm/__snapshots__/package.spec.js.snap b/test/manager/nvm/__snapshots__/package.spec.js.snap new file mode 100644 index 0000000000..acf0751f45 --- /dev/null +++ b/test/manager/nvm/__snapshots__/package.spec.js.snap @@ -0,0 +1,3 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`lib/workers/package/node getPackageUpdates returns result if needing updates 1`] = `Array []`; diff --git a/test/manager/nvm/__snapshots__/update.spec.js.snap b/test/manager/nvm/__snapshots__/update.spec.js.snap new file mode 100644 index 0000000000..e938db537a --- /dev/null +++ b/test/manager/nvm/__snapshots__/update.spec.js.snap @@ -0,0 +1,6 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`manager/nvm/update setNewValue updates values 1`] = ` +"8.9.1 +" +`; diff --git a/test/manager/nvm/extract.spec.js b/test/manager/nvm/extract.spec.js new file mode 100644 index 0000000000..d13e4d2d45 --- /dev/null +++ b/test/manager/nvm/extract.spec.js @@ -0,0 +1,10 @@ +const { extractDependencies } = require('../../../lib/manager/nvm/extract'); + +describe('lib/manager/nvm/extract', () => { + describe('extractDependencies()', () => { + it('returns a result', () => { + const res = extractDependencies('8.4.0\n'); + expect(res).toMatchSnapshot(); + }); + }); +}); diff --git a/test/manager/nvm/package.spec.js b/test/manager/nvm/package.spec.js new file mode 100644 index 0000000000..1c53f378b2 --- /dev/null +++ b/test/manager/nvm/package.spec.js @@ -0,0 +1,22 @@ +const node = require('../../../lib/manager/nvm/package'); +const defaultConfig = require('../../../lib/config/defaults').getConfig(); + +describe('lib/workers/package/node', () => { + describe('getPackageUpdates', () => { + let config; + beforeEach(() => { + config = { + ...defaultConfig, + }; + }); + it('returns empty if matching', async () => { + config.currentVersion = ['6', '8']; + config.supportPolicy = ['lts_active']; + expect(await node.getPackageUpdates(config)).toEqual([]); + }); + it('returns result if needing updates', async () => { + config.currentVersion = ['6', '8']; + expect(await node.getPackageUpdates(config)).toMatchSnapshot(); + }); + }); +}); diff --git a/test/manager/nvm/update.spec.js b/test/manager/nvm/update.spec.js new file mode 100644 index 0000000000..529499f600 --- /dev/null +++ b/test/manager/nvm/update.spec.js @@ -0,0 +1,13 @@ +const nodefile = require('../../../lib/manager/nvm/update'); + +describe('manager/nvm/update', () => { + describe('setNewValue', () => { + it('updates values', () => { + const upgrade = { + newVersion: '8.9.1', + }; + const res = nodefile.setNewValue('8.9.0\n', upgrade); + expect(res).toMatchSnapshot(); + }); + }); +}); diff --git a/test/manager/resolve.spec.js b/test/manager/resolve.spec.js index c30ff35c6d..78c9d002b4 100644 --- a/test/manager/resolve.spec.js +++ b/test/manager/resolve.spec.js @@ -94,18 +94,19 @@ describe('manager/resolve', () => { expect(res.packageFiles).toMatchSnapshot(); expect(res.warnings).toHaveLength(0); }); - it('detects meteor and docker and travis and bazel', async () => { + it('detects meteor and docker and travis and bazel and nvm', async () => { config.packageFiles = [ 'package.js', 'Dockerfile', '.travis.yml', 'WORKSPACE', + '.nvmrc', ]; platform.getFile.mockReturnValueOnce('{}'); // package.js platform.getFile.mockReturnValueOnce('# comment\nFROM node:8\n'); // Dockerfile - platform.getFile.mockReturnValueOnce('hello: world\n'); // Dockerfile platform.getFile.mockReturnValueOnce('# travis'); // .travis.yml platform.getFile.mockReturnValueOnce('# WORKSPACE'); // Dockerfile + platform.getFile.mockReturnValueOnce('8.9\n'); // Dockerfile const res = await resolvePackageFiles(config); expect(res.packageFiles).toMatchSnapshot(); }); @@ -116,6 +117,7 @@ describe('manager/resolve', () => { '.travis.yml', 'WORKSPACE', 'package.js', + '.nvmrc', ]; platform.getFile.mockReturnValueOnce('# comment\n'); // Dockerfile const res = await resolvePackageFiles(config); diff --git a/website/docs/_posts/2017-10-05-configuration-options.md b/website/docs/_posts/2017-10-05-configuration-options.md index 991e8b6b65..f41a95b7d2 100644 --- a/website/docs/_posts/2017-10-05-configuration-options.md +++ b/website/docs/_posts/2017-10-05-configuration-options.md @@ -551,6 +551,17 @@ A string copy of npmrc file. See https://renovateapp.com/docs/deep-dives/private-modules for details on how this is used. +## nvm + +Configuration specific for `.nvmrc` files. + +| name | value | +| ------- | ----------------- | +| type | object | +| default | { enabled: true } | + +For settings common to all node.js version updates (e.g. travis, nvm, etc) you can use the `node` object instead. + ## optionalDependencies Configuration specific for `package.json > optionalDependencies`. -- GitLab