From 9c1b7d78cd9054ded00ee179ecbe97fad10a46b1 Mon Sep 17 00:00:00 2001 From: Rhys Arkins <rhys@keylocation.sg> Date: Fri, 3 Nov 2017 09:06:42 +0100 Subject: [PATCH] refactor: move monorepos logic to npm manager (#1091) * refactor: move monorepos logic to npm manager * fix test --- lib/manager/npm/monorepos.js | 56 +++++++++++++ lib/workers/repository/apis.js | 56 ------------- lib/workers/repository/index.js | 4 +- .../npm/__snapshots__/monorepo.spec.js.snap | 24 ++++++ test/manager/npm/monorepo.spec.js | 80 +++++++++++++++++++ .../__snapshots__/apis.spec.js.snap | 23 ------ test/workers/repository/apis.spec.js | 80 ------------------- 7 files changed, 163 insertions(+), 160 deletions(-) create mode 100644 lib/manager/npm/monorepos.js create mode 100644 test/manager/npm/__snapshots__/monorepo.spec.js.snap create mode 100644 test/manager/npm/monorepo.spec.js diff --git a/lib/manager/npm/monorepos.js b/lib/manager/npm/monorepos.js new file mode 100644 index 0000000000..a0a5870c01 --- /dev/null +++ b/lib/manager/npm/monorepos.js @@ -0,0 +1,56 @@ +const minimatch = require('minimatch'); +const path = require('path'); + +module.exports = { + checkMonorepos, +}; + +async function checkMonorepos(config) { + const { logger } = config; + const monorepoPackages = []; + let workspaceDir; + // yarn workspaces + let workspaces = []; + for (const packageFile of config.packageFiles) { + if ( + packageFile.packageFile && + packageFile.packageFile.endsWith('package.json') && + packageFile.content.workspaces + ) { + workspaceDir = path.dirname(packageFile.packageFile); + logger.info(`workspaceDir=${config.workspaceDir}`); + ({ workspaces } = packageFile.content); + } + } + if (workspaces.length) { + logger.debug({ workspaces }, 'Found yarn workspaces'); + } + for (const workspace of workspaces) { + const basePath = path.join(workspaceDir, workspace); + logger.info(`basePath=${basePath}`); + for (const packageFile of config.packageFiles) { + if (minimatch(path.dirname(packageFile.packageFile), basePath)) { + logger.info(`Matched ${packageFile.packageFile}`); + const depName = packageFile.content.name; + monorepoPackages.push(depName); + packageFile.workspaceDir = workspaceDir; + } + } + } + // lerna + const lernaJson = await config.api.getFileJson('lerna.json'); + if (lernaJson && lernaJson.packages) { + logger.debug({ lernaJson }, 'Found lerna config'); + for (const packageGlob of lernaJson.packages) { + for (const packageFile of config.packageFiles) { + if (minimatch(path.dirname(packageFile.packageFile), packageGlob)) { + const depName = packageFile.content.name; + if (!monorepoPackages.includes(depName)) { + monorepoPackages.push(depName); + } + } + } + } + } + return { ...config, monorepoPackages, workspaceDir }; +} diff --git a/lib/workers/repository/apis.js b/lib/workers/repository/apis.js index 5c76652271..e78af34e8b 100644 --- a/lib/workers/repository/apis.js +++ b/lib/workers/repository/apis.js @@ -1,4 +1,3 @@ -const minimatch = require('minimatch'); const conventionalCommitsDetector = require('conventional-commits-detector'); const path = require('path'); const jsonValidator = require('json-dup-key-validator'); @@ -14,7 +13,6 @@ const { migrateAndValidate } = require('../../config/migrate-validate'); module.exports = { detectSemanticCommits, - checkMonorepos, getNpmrc, initApis, mergeRenovateJson, @@ -36,60 +34,6 @@ async function detectSemanticCommits(config) { return true; } -async function checkMonorepos(input) { - const config = { ...input }; - const { logger } = config; - config.monorepoPackages = []; - // yarn workspaces - let workspaces = []; - for (const packageFile of config.packageFiles) { - if ( - packageFile.packageFile && - packageFile.packageFile.endsWith('package.json') && - packageFile.content.workspaces - ) { - config.workspaceDir = path.dirname(packageFile.packageFile); - logger.info(`workspaceDir=${config.workspaceDir}`); - ({ workspaces } = packageFile.content); - } - } - if (workspaces.length) { - logger.debug({ workspaces }, 'Found yarn workspaces'); - } - for (const workspace of workspaces) { - const basePath = path.join(config.workspaceDir, workspace); - logger.info(`basePath=${basePath}`); - for (const packageFile of config.packageFiles) { - if (minimatch(path.dirname(packageFile.packageFile), basePath)) { - logger.info(`Matched ${packageFile.packageFile}`); - const depName = packageFile.content.name; - config.monorepoPackages.push(depName); - packageFile.workspaceDir = config.workspaceDir; - } - } - } - // lerna - const lernaJson = await config.api.getFileJson('lerna.json'); - if (!lernaJson) { - return config; - } - logger.debug({ lernaJson }, 'Found lerna config'); - if (!lernaJson.packages) { - return config; - } - for (const packageGlob of lernaJson.packages) { - for (const packageFile of config.packageFiles) { - if (minimatch(path.dirname(packageFile.packageFile), packageGlob)) { - const depName = packageFile.content.name; - if (!config.monorepoPackages.includes(depName)) { - config.monorepoPackages.push(depName); - } - } - } - } - return config; -} - // Check for .npmrc in repository and pass it to npm api if found async function getNpmrc(config) { if (config.ignoreNpmrcFile) { diff --git a/lib/workers/repository/index.js b/lib/workers/repository/index.js index 73d9b14079..a65e7c28ba 100644 --- a/lib/workers/repository/index.js +++ b/lib/workers/repository/index.js @@ -9,6 +9,8 @@ const onboarding = require('./onboarding'); const upgrades = require('./upgrades'); const cleanup = require('./cleanup'); +const { checkMonorepos } = require('../../manager/npm/monorepos'); + module.exports = { pinDependenciesFirst, renovateRepository, @@ -104,7 +106,7 @@ async function renovateRepository(repoConfig, token) { } logger.debug('Resolving package files and content'); config = await apis.resolvePackageFiles(config); - config = await apis.checkMonorepos(config); + config = await checkMonorepos(config); logger.trace({ config }, 'post-packageFiles config'); // TODO: why is this fix needed?! config.logger = logger; diff --git a/test/manager/npm/__snapshots__/monorepo.spec.js.snap b/test/manager/npm/__snapshots__/monorepo.spec.js.snap new file mode 100644 index 0000000000..95ba2aea02 --- /dev/null +++ b/test/manager/npm/__snapshots__/monorepo.spec.js.snap @@ -0,0 +1,24 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`manager/npm/monorepo checkMonorepos adds lerna packages 1`] = ` +Array [ + "@a/b", + "@a/c", +] +`; + +exports[`manager/npm/monorepo checkMonorepos adds nested yarn workspaces 1`] = ` +Array [ + "@a/b", + "@a/c", +] +`; + +exports[`manager/npm/monorepo checkMonorepos adds yarn workspaces 1`] = ` +Array [ + "@a/b", + "@a/c", +] +`; + +exports[`manager/npm/monorepo checkMonorepos skips if no lerna packages 1`] = `Array []`; diff --git a/test/manager/npm/monorepo.spec.js b/test/manager/npm/monorepo.spec.js new file mode 100644 index 0000000000..4a4339a41f --- /dev/null +++ b/test/manager/npm/monorepo.spec.js @@ -0,0 +1,80 @@ +const { checkMonorepos } = require('../../../lib/manager/npm/monorepos'); + +let config; +beforeEach(() => { + jest.resetAllMocks(); + config = { ...require('../../_fixtures/config') }; + config.errors = []; + config.warnings = []; +}); + +describe('manager/npm/monorepo', () => { + describe('checkMonorepos', () => { + it('adds yarn workspaces', async () => { + config.packageFiles = [ + { + packageFile: 'package.json', + content: { workspaces: ['packages/*'] }, + }, + { + packageFile: 'packages/something/package.json', + content: { name: '@a/b' }, + }, + { + packageFile: 'packages/something-else/package.json', + content: { name: '@a/c' }, + }, + ]; + const res = await checkMonorepos(config); + expect(res.monorepoPackages).toMatchSnapshot(); + }); + it('adds nested yarn workspaces', async () => { + config.packageFiles = [ + { + packageFile: 'frontend/package.json', + content: { workspaces: ['packages/*'] }, + }, + { + packageFile: 'frontend/packages/something/package.json', + content: { name: '@a/b' }, + }, + { + packageFile: 'frontend/packages/something-else/package.json', + content: { name: '@a/c' }, + }, + ]; + const res = await checkMonorepos(config); + expect(res.monorepoPackages).toMatchSnapshot(); + }); + it('adds lerna packages', async () => { + config.packageFiles = [ + { + packageFile: 'package.json', + content: {}, + }, + { + packageFile: 'packages/something/package.json', + content: { name: '@a/b' }, + }, + { + packageFile: 'packages/something-else/package.json', + content: { name: '@a/c' }, + }, + ]; + config.api.getFileJson.mockReturnValue({ packages: ['packages/*'] }); + const res = await checkMonorepos(config); + expect(res.monorepoPackages).toMatchSnapshot(); + }); + it('skips if no lerna packages', async () => { + config.packageFiles = [ + { + packageFile: 'package.json', + content: {}, + }, + ]; + config.api.getFileJson.mockReturnValue({}); + const res = await checkMonorepos(config); + expect(res.monorepoPackages).toMatchSnapshot(); + }); + }); +}); diff --git a/test/workers/repository/__snapshots__/apis.spec.js.snap b/test/workers/repository/__snapshots__/apis.spec.js.snap index 8d5fe7bdd6..e1fd6165dd 100644 --- a/test/workers/repository/__snapshots__/apis.spec.js.snap +++ b/test/workers/repository/__snapshots__/apis.spec.js.snap @@ -1,28 +1,5 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`workers/repository/apis checkMonorepos adds lerna packages 1`] = ` -Array [ - "@a/b", - "@a/c", -] -`; - -exports[`workers/repository/apis checkMonorepos adds nested yarn workspaces 1`] = ` -Array [ - "@a/b", - "@a/c", -] -`; - -exports[`workers/repository/apis checkMonorepos adds yarn workspaces 1`] = ` -Array [ - "@a/b", - "@a/c", -] -`; - -exports[`workers/repository/apis checkMonorepos skips if no lerna packages 1`] = `Array []`; - exports[`workers/repository/apis initApis(config) throws if unknown platform 1`] = `"Unknown platform: foo"`; exports[`workers/repository/apis mergeRenovateJson(config) returns error in config if renovate.json cannot be parsed 1`] = ` diff --git a/test/workers/repository/apis.spec.js b/test/workers/repository/apis.spec.js index 5d9ae3fdbe..5006d051c0 100644 --- a/test/workers/repository/apis.spec.js +++ b/test/workers/repository/apis.spec.js @@ -7,8 +7,6 @@ const githubApi = require('../../../lib/platform/github'); const gitlabApi = require('../../../lib/platform/gitlab'); const npmApi = require('../../../lib/manager/npm/registry'); -const defaultConfig = require('../../../lib/config/defaults').getConfig(); - jest.mock('../../../lib/platform/github'); jest.mock('../../../lib/platform/gitlab'); jest.mock('../../../lib/manager/npm/registry'); @@ -52,84 +50,6 @@ describe('workers/repository/apis', () => { expect(await apis.getNpmrc(config)).toMatchObject(config); }); }); - describe('checkMonorepos', () => { - let config; - beforeEach(() => { - config = { - ...defaultConfig, - api: { - getFileJson: jest.fn(), - }, - logger, - }; - }); - it('adds yarn workspaces', async () => { - config.packageFiles = [ - { - packageFile: 'package.json', - content: { workspaces: ['packages/*'] }, - }, - { - packageFile: 'packages/something/package.json', - content: { name: '@a/b' }, - }, - { - packageFile: 'packages/something-else/package.json', - content: { name: '@a/c' }, - }, - ]; - const res = await apis.checkMonorepos(config); - expect(res.monorepoPackages).toMatchSnapshot(); - }); - it('adds nested yarn workspaces', async () => { - config.packageFiles = [ - { - packageFile: 'frontend/package.json', - content: { workspaces: ['packages/*'] }, - }, - { - packageFile: 'frontend/packages/something/package.json', - content: { name: '@a/b' }, - }, - { - packageFile: 'frontend/packages/something-else/package.json', - content: { name: '@a/c' }, - }, - ]; - const res = await apis.checkMonorepos(config); - expect(res.monorepoPackages).toMatchSnapshot(); - }); - it('adds lerna packages', async () => { - config.packageFiles = [ - { - packageFile: 'package.json', - content: {}, - }, - { - packageFile: 'packages/something/package.json', - content: { name: '@a/b' }, - }, - { - packageFile: 'packages/something-else/package.json', - content: { name: '@a/c' }, - }, - ]; - config.api.getFileJson.mockReturnValue({ packages: ['packages/*'] }); - const res = await apis.checkMonorepos(config); - expect(res.monorepoPackages).toMatchSnapshot(); - }); - it('skips if no lerna packages', async () => { - config.packageFiles = [ - { - packageFile: 'package.json', - content: {}, - }, - ]; - config.api.getFileJson.mockReturnValue({}); - const res = await apis.checkMonorepos(config); - expect(res.monorepoPackages).toMatchSnapshot(); - }); - }); describe('detectSemanticCommits', () => { it('disables semantic commits', async () => { const config = { -- GitLab